package org.eclipse.equinox.p2.operations;

import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.operations.Activator;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.query.*;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

public class SimpleCaseFactory {
	private IProvisioningAgent getAgent() {
		Collection<ServiceReference<IProvisioningAgent>> ref = null;
		try {
			ref = Activator.getContext().getServiceReferences(IProvisioningAgent.class, '(' + IProvisioningAgent.SERVICE_CURRENT + '=' + Boolean.TRUE.toString() + ')');
		} catch (InvalidSyntaxException e) {
			//ignore can't happen since we write the filter ourselves
		}
		if (ref == null || ref.size() == 0)
			throw new IllegalStateException("p2 is not configured properly. No provisioning agent could be found.");
		IProvisioningAgent agent = Activator.getContext().getService(ref.iterator().next());
		Activator.getContext().ungetService(ref.iterator().next());
		return agent;
	}

	private Collection<IInstallableUnit> gatherIUs(ProvisioningContext context, List<IVersionedId> featureIds, IProgressMonitor monitor) {
		Collection<IInstallableUnit> unitsToInstall = new ArrayList<IInstallableUnit>(featureIds.size());

		for (IVersionedId versionedId : featureIds) {
			if (featureIds instanceof IInstallableUnit) {
				unitsToInstall.add((IInstallableUnit) versionedId);
				continue;
			}

			IQuery<IInstallableUnit> installableUnits = QueryUtil.createIUQuery(versionedId.getId(), versionedId.getVersion());
			IQueryResult<IInstallableUnit> ius = context.getMetadata(monitor).query(installableUnits, monitor);
			//			if (ius.isEmpty())
			//				Do something smart. like throw an exception
			//Add the first IU
			Iterator<IInstallableUnit> iuIt = ius.iterator();
			unitsToInstall.add(iuIt.next());

			if (iuIt.hasNext())
				System.out.println("Log the fact that we have a problem");
		}
		return unitsToInstall;
	}

	public InstallOperation createOperation(List<URI> repos, List<IVersionedId> toInstall, IProgressMonitor monitor) {
		IProvisioningAgent agent = getAgent();
		//add the repos
		ProvisioningContext ctx = createProvisioningContext(repos, agent);

		//find the ius to install
		//create the operation
		InstallOperation resultingOperation = new InstallOperation(new ProvisioningSession(agent), gatherIUs(ctx, toInstall, monitor));
		resultingOperation.setProvisioningContext(ctx);
		resultingOperation.setProfileId(IProfileRegistry.SELF);

		return resultingOperation;
	}

	private ProvisioningContext createProvisioningContext(List<URI> repos, IProvisioningAgent agent) {
		ProvisioningContext ctx = new ProvisioningContext(agent);
		ctx.setMetadataRepositories(repos.toArray(new URI[repos.size()]));
		ctx.setArtifactRepositories(repos.toArray(new URI[repos.size()]));
		return ctx;
	}
}
