/*******************************************************************************
 * Copyright (c) 2009, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.p2.internal.repository.tools;

import java.net.MalformedURLException;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.internal.p2.artifact.repository.CompositeArtifactRepository;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.metadata.repository.CompositeMetadataRepository;
import org.eclipse.equinox.internal.p2.repository.helpers.RepositoryHelper;
import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.repository.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.ServiceReference;

public abstract class AbstractApplication {
	protected boolean removeAddedRepositories = true;

	protected List<RepositoryDescriptor> sourceRepositories = new ArrayList<RepositoryDescriptor>(); //List of repository descriptors
	protected List<URI> artifactReposToRemove = new ArrayList<URI>();
	protected List<URI> metadataReposToRemove = new ArrayList<URI>();
	protected List<IInstallableUnit> sourceIUs = new ArrayList<IInstallableUnit>();
	private List<RepositoryDescriptor> destinationRepos = new ArrayList<RepositoryDescriptor>();

	protected IArtifactRepository destinationArtifactRepository = null;
	protected IMetadataRepository destinationMetadataRepository = null;

	private CompositeMetadataRepository compositeMetadataRepository = null;
	private CompositeArtifactRepository compositeArtifactRepository = null;

	protected IProvisioningAgent agent;

	public AbstractApplication() {
		super();
		try {
			setupAgent();
		} catch (ProvisionException e) {
			LogHelper.log(e);
		}
	}

	private void setupAgent() throws ProvisionException {
		//note if we ever wanted these applications to act on a different agent than
		//the currently running system we would need to set it here
		ServiceReference<IProvisioningAgent> agentRef = Activator.getBundleContext().getServiceReference(IProvisioningAgent.class);
		if (agentRef != null) {
			agent = Activator.getBundleContext().getService(agentRef);
			if (agent != null)
				return;
		}
		//there is no agent around so we need to create one
		ServiceReference<IProvisioningAgentProvider> providerRef = Activator.getBundleContext().getServiceReference(IProvisioningAgentProvider.class);
		if (providerRef == null)
			throw new RuntimeException("No provisioning agent provider is available"); //$NON-NLS-1$
		IProvisioningAgentProvider provider = Activator.getBundleContext().getService(providerRef);
		if (provider == null)
			throw new RuntimeException("No provisioning agent provider is available"); //$NON-NLS-1$
		//obtain agent for currently running system
		agent = provider.createAgent(null);
		Activator.getBundleContext().ungetService(providerRef);
	}

	public void setSourceIUs(List<IInstallableUnit> ius) {
		sourceIUs = ius;
	}

	protected void finalizeRepositories() {
		if (removeAddedRepositories) {
			IArtifactRepositoryManager artifactRepositoryManager = getArtifactRepositoryManager();
			for (URI uri : artifactReposToRemove)
				artifactRepositoryManager.removeRepository(uri);
			IMetadataRepositoryManager metadataRepositoryManager = getMetadataRepositoryManager();
			for (URI uri : metadataReposToRemove)
				metadataRepositoryManager.removeRepository(uri);
		}
		metadataReposToRemove = null;
		artifactReposToRemove = null;
		compositeArtifactRepository = null;
		compositeMetadataRepository = null;
		destinationArtifactRepository = null;
		destinationMetadataRepository = null;
	}

	protected IMetadataRepositoryManager getMetadataRepositoryManager() {
		return (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
	}

	protected IArtifactRepositoryManager getArtifactRepositoryManager() {
		return (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
	}

	public void initializeRepos(IProgressMonitor progress) throws ProvisionException {
		IArtifactRepositoryManager artifactRepositoryManager = getArtifactRepositoryManager();
		IMetadataRepositoryManager metadataRepositoryManager = getMetadataRepositoryManager();
		URI curLocation = null;
		for (RepositoryDescriptor repo : sourceRepositories) {
			try {
				curLocation = repo.getRepoLocation();
				if (repo.isBoth()) {
					addRepository(artifactRepositoryManager, curLocation, 0, progress);
					addRepository(metadataRepositoryManager, curLocation, 0, progress);
				} else if (repo.isArtifact())
					addRepository(artifactRepositoryManager, curLocation, 0, progress);
				else if (repo.isMetadata())
					addRepository(metadataRepositoryManager, curLocation, 0, progress);
				else
					throw new ProvisionException(NLS.bind(Messages.unknown_repository_type, repo.getRepoLocation()));
			} catch (ProvisionException e) {
				if (e.getCause() instanceof MalformedURLException) {
					throw new ProvisionException(NLS.bind(Messages.exception_invalidSource, curLocation), e);
				} else if (e.getStatus().getCode() == ProvisionException.REPOSITORY_NOT_FOUND && repo.isOptional()) {
					continue;
				}
				throw e;
			}
		}
		processDestinationRepos(artifactRepositoryManager, metadataRepositoryManager);
	}

	//Helper to add a repository. It takes care of adding the repos to the deletion list and loading it 
	protected IMetadataRepository addRepository(IMetadataRepositoryManager manager, URI location, int flags, IProgressMonitor monitor) throws ProvisionException {
		if (!manager.contains(location))
			metadataReposToRemove.add(location);
		return manager.loadRepository(location, flags, monitor);
	}

	//Helper to add a repository. It takes care of adding the repos to the deletion list and loading it
	protected IArtifactRepository addRepository(IArtifactRepositoryManager manager, URI location, int flags, IProgressMonitor monitor) throws ProvisionException {
		if (!manager.contains(location))
			artifactReposToRemove.add(location);
		return manager.loadRepository(location, flags, monitor);
	}

	private void processDestinationRepos(IArtifactRepositoryManager artifactRepositoryManager, IMetadataRepositoryManager metadataRepositoryManager) throws ProvisionException {
		RepositoryDescriptor artifactRepoDescriptor = null;
		RepositoryDescriptor metadataRepoDescriptor = null;

		Iterator<RepositoryDescriptor> iter = destinationRepos.iterator();
		while (iter.hasNext() && (artifactRepoDescriptor == null || metadataRepoDescriptor == null)) {
			RepositoryDescriptor repo = iter.next();
			if (repo.isArtifact() && artifactRepoDescriptor == null)
				artifactRepoDescriptor = repo;
			if (repo.isMetadata() && metadataRepoDescriptor == null)
				metadataRepoDescriptor = repo;
		}

		if (artifactRepoDescriptor != null)
			destinationArtifactRepository = initializeDestination(artifactRepoDescriptor, artifactRepositoryManager);
		if (metadataRepoDescriptor != null)
			destinationMetadataRepository = initializeDestination(metadataRepoDescriptor, metadataRepositoryManager);

		if (destinationMetadataRepository == null && destinationArtifactRepository == null)
			throw new ProvisionException(Messages.AbstractApplication_no_valid_destinations);
	}

	public IMetadataRepository getDestinationMetadataRepository() {
		return destinationMetadataRepository;
	}

	public IArtifactRepository getDestinationArtifactRepository() {
		return destinationArtifactRepository;
	}

	protected IMetadataRepository initializeDestination(RepositoryDescriptor toInit, IMetadataRepositoryManager mgr) throws ProvisionException {
		try {
			IMetadataRepository repository = addRepository(mgr, toInit.getRepoLocation(), IRepositoryManager.REPOSITORY_HINT_MODIFIABLE, null);
			if (initDestinationRepository(repository, toInit))
				return repository;
		} catch (ProvisionException e) {
			//fall through and create a new repository below
		}

		IMetadataRepository source = null;
		try {
			if (toInit.getFormat() != null)
				source = mgr.loadRepository(toInit.getFormat(), 0, null);
		} catch (ProvisionException e) {
			//Ignore.
		}
		//This code assumes source has been successfully loaded before this point
		//No existing repository; create a new repository at destinationLocation but with source's attributes.
		try {
			IMetadataRepository result = mgr.createRepository(toInit.getRepoLocation(), toInit.getName() != null ? toInit.getName() : (source != null ? source.getName() : toInit.getRepoLocation().toString()), IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, source != null ? source.getProperties() : null);
			if (toInit.isCompressed() && !result.getProperties().containsKey(IRepository.PROP_COMPRESSED))
				result.setProperty(IRepository.PROP_COMPRESSED, "true"); //$NON-NLS-1$
			return (IMetadataRepository) RepositoryHelper.validDestinationRepository(result);
		} catch (UnsupportedOperationException e) {
			throw new ProvisionException(NLS.bind(Messages.exception_invalidDestination, toInit.getRepoLocation()), e.getCause());
		}
	}

	protected IArtifactRepository initializeDestination(RepositoryDescriptor toInit, IArtifactRepositoryManager mgr) throws ProvisionException {
		try {
			IArtifactRepository repository = addRepository(mgr, toInit.getRepoLocation(), IRepositoryManager.REPOSITORY_HINT_MODIFIABLE, null);
			if (initDestinationRepository(repository, toInit))
				return repository;
		} catch (ProvisionException e) {
			//fall through and create a new repository below
		}
		IArtifactRepository source = null;
		try {
			if (toInit.getFormat() != null)
				source = mgr.loadRepository(toInit.getFormat(), 0, null);
		} catch (ProvisionException e) {
			//Ignore.
		}
		//This code assumes source has been successfully loaded before this point
		//No existing repository; create a new repository at destinationLocation but with source's attributes.
		// TODO for now create a Simple repo by default.
		try {
			IArtifactRepository result = mgr.createRepository(toInit.getRepoLocation(), toInit.getName() != null ? toInit.getName() : (source != null ? source.getName() : toInit.getRepoLocation().toString()), IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, source != null ? source.getProperties() : null);
			if (toInit.isCompressed() && !result.getProperties().containsKey(IRepository.PROP_COMPRESSED))
				result.setProperty(IRepository.PROP_COMPRESSED, "true"); //$NON-NLS-1$
			return (IArtifactRepository) RepositoryHelper.validDestinationRepository(result);
		} catch (UnsupportedOperationException e) {
			throw new ProvisionException(NLS.bind(Messages.exception_invalidDestination, toInit.getRepoLocation()), e.getCause());
		}
	}

	protected boolean initDestinationRepository(IRepository<?> repository, RepositoryDescriptor descriptor) {
		if (repository != null && repository.isModifiable()) {
			if (descriptor.getName() != null)
				repository.setProperty(IRepository.PROP_NAME, descriptor.getName());
			if (repository instanceof ICompositeRepository<?> && !descriptor.isAppend())
				((ICompositeRepository<?>) repository).removeAllChildren();
			else if (repository instanceof IMetadataRepository && !descriptor.isAppend())
				((IMetadataRepository) repository).removeAll();
			else if (repository instanceof IArtifactRepository && !descriptor.isAppend())
				((IArtifactRepository) repository).removeAll();
			return true;
		}
		return false;
	}

	public IMetadataRepository getCompositeMetadataRepository() {
		if (compositeMetadataRepository == null) {
			compositeMetadataRepository = CompositeMetadataRepository.createMemoryComposite(agent);
			for (RepositoryDescriptor repo : sourceRepositories) {
				if (repo.isMetadata())
					compositeMetadataRepository.addChild(repo.getRepoLocation());
			}
		}
		return compositeMetadataRepository;
	}

	public IArtifactRepository getCompositeArtifactRepository() {
		if (compositeArtifactRepository == null) {
			compositeArtifactRepository = CompositeArtifactRepository.createMemoryComposite(agent);
			for (RepositoryDescriptor repo : sourceRepositories) {
				if (repo.isArtifact())
					compositeArtifactRepository.addChild(repo.getRepoLocation());
			}
		}
		return compositeArtifactRepository;
	}

	public boolean hasArtifactSources() {
		return ((ICompositeRepository<?>) getCompositeArtifactRepository()).getChildren().size() > 0;
	}

	public boolean hasMetadataSources() {
		return ((ICompositeRepository<?>) getCompositeMetadataRepository()).getChildren().size() > 0;
	}

	public abstract IStatus run(IProgressMonitor monitor) throws ProvisionException;

	public void addDestination(RepositoryDescriptor descriptor) {
		destinationRepos.add(descriptor);
	}

	public void addSource(RepositoryDescriptor repo) {
		sourceRepositories.add(repo);
	}
}