/*******************************************************************************
 * Copyright (c) 2007, 2008 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.internal.p2.director;

import java.net.URL;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.resolution.ResolutionHelper;
import org.eclipse.equinox.internal.p2.rollback.FormerState;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.director.*;
import org.eclipse.equinox.internal.provisional.p2.engine.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.UpdateQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.internal.provisional.p2.query.IQueryable;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.NLS;

public class SimplePlanner implements IPlanner {
	private static final int ExpandWork = 12;
	private static final String PLANNER_MARKER = "private.org.eclipse.equinox.p2.planner.installed"; //$NON-NLS-1$

	private IInstallableUnit[] getInstallableUnits(IProfile profile) {
		return (IInstallableUnit[]) profile.query(InstallableUnitQuery.ANY, new Collector(), null).toArray(IInstallableUnit.class);
	}

	private IProfile getProfile(String profileId) {
		IProfileRegistry profileRegistry = (IProfileRegistry) ServiceHelper.getService(DirectorActivator.context, IProfileRegistry.class.getName());
		if (profileRegistry == null)
			return null;
		return profileRegistry.getProfile(profileId);
	}

	private ProvisioningPlan generateProvisioningPlan(IStatus status, Collection fromState, Collection toState, List fromStateOrder, List newStateOrder, ProfileChangeRequest changeRequest) {
		InstallableUnitOperand[] iuOperands = generateOperations(fromState, toState, fromStateOrder, newStateOrder);
		PropertyOperand[] propertyOperands = generatePropertyOperations(changeRequest);

		Operand[] operands = new Operand[iuOperands.length + propertyOperands.length];
		System.arraycopy(iuOperands, 0, operands, 0, iuOperands.length);
		System.arraycopy(propertyOperands, 0, operands, iuOperands.length, propertyOperands.length);

		if (status == null)
			status = Status.OK_STATUS;
		return new ProvisioningPlan(status, operands);
	}

	private PropertyOperand[] generatePropertyOperations(ProfileChangeRequest profileChangeRequest) {
		IProfile profile = profileChangeRequest.getProfile();
		List operands = new ArrayList();
		// First deal with profile properties to remove.  Only generate an operand if the property was there in the first place
		String[] toRemove = profileChangeRequest.getPropertiesToRemove();
		Map existingProperties = profile.getProperties();
		for (int i = 0; i < toRemove.length; i++) {
			if (existingProperties.containsKey(toRemove[i]))
				operands.add(new PropertyOperand(toRemove[i], existingProperties.get(toRemove[i]), null));
		}
		// Now deal with profile property changes/additions
		Map propertyChanges = profileChangeRequest.getPropertiesToAdd();
		Iterator iter = propertyChanges.keySet().iterator();
		while (iter.hasNext()) {
			String key = (String) iter.next();
			operands.add(new PropertyOperand(key, existingProperties.get(key), propertyChanges.get(key)));
		}
		// Now deal with iu property changes/additions.  
		// TODO we aren't yet checking that the IU will exist in the final profile, will the engine do this?
		Map allIUPropertyChanges = profileChangeRequest.getInstallableUnitProfilePropertiesToAdd();
		iter = allIUPropertyChanges.keySet().iterator();
		while (iter.hasNext()) {
			IInstallableUnit iu = (IInstallableUnit) iter.next();
			Map iuPropertyChanges = (Map) allIUPropertyChanges.get(iu);
			Iterator iuPropIter = iuPropertyChanges.keySet().iterator();
			while (iuPropIter.hasNext()) {
				String key = (String) iuPropIter.next();
				Object oldValue = profile.getInstallableUnitProperty(iu, key);
				operands.add(new InstallableUnitPropertyOperand(iu, key, oldValue, iuPropertyChanges.get(key)));
			}
		}
		// Now deal with iu property removals.
		// TODO we could optimize by not generating property removals for IU's that aren't there or won't be there.  
		Map allIUPropertyDeletions = profileChangeRequest.getInstallableUnitProfilePropertiesToRemove();
		iter = allIUPropertyDeletions.keySet().iterator();
		while (iter.hasNext()) {
			IInstallableUnit iu = (IInstallableUnit) iter.next();
			Map existingIUProperties = profile.getInstallableUnitProperties(iu);
			List iuPropertyRemovals = (List) allIUPropertyDeletions.get(iu);
			for (Iterator it = iuPropertyRemovals.iterator(); it.hasNext();) {
				String key = (String) it.next();
				if (existingIUProperties.containsKey(key))
					operands.add(new InstallableUnitPropertyOperand(iu, key, existingIUProperties.get(key), null));
			}

		}
		return (PropertyOperand[]) operands.toArray(new PropertyOperand[operands.size()]);
	}

	private InstallableUnitOperand[] generateOperations(Collection fromState, Collection toState, List fromStateOrder, List newStateOrder) {
		return sortOperations(new OperationGenerator().generateOperation(fromState, toState), newStateOrder, fromStateOrder);
	}

	private InstallableUnitOperand[] sortOperations(InstallableUnitOperand[] toSort, List installOrder, List uninstallOrder) {
		List updateOp = new ArrayList();
		for (int i = 0; i < toSort.length; i++) {
			InstallableUnitOperand op = toSort[i];
			if (op.first() == null && op.second() != null) {
				installOrder.set(installOrder.indexOf(op.second()), op);
				continue;
			}
			if (op.first() != null && op.second() == null) {
				uninstallOrder.set(uninstallOrder.indexOf(op.first()), op);
				continue;
			}
			if (op.first() != null && op.second() != null) {
				updateOp.add(op);
				continue;
			}
		}
		int i = 0;
		for (Iterator iterator = installOrder.iterator(); iterator.hasNext();) {
			Object elt = iterator.next();
			if (elt instanceof InstallableUnitOperand) {
				toSort[i++] = (InstallableUnitOperand) elt;
			}
		}
		for (Iterator iterator = uninstallOrder.iterator(); iterator.hasNext();) {
			Object elt = iterator.next();
			if (elt instanceof InstallableUnitOperand) {
				toSort[i++] = (InstallableUnitOperand) elt;
			}
		}
		for (Iterator iterator = updateOp.iterator(); iterator.hasNext();) {
			Object elt = iterator.next();
			if (elt instanceof InstallableUnitOperand) {
				toSort[i++] = (InstallableUnitOperand) elt;
			}
		}
		return toSort;
	}

	public ProvisioningPlan getRevertPlan(IInstallableUnit profileSnapshot, ProvisioningContext context, IProgressMonitor monitor) {
		SubMonitor sub = SubMonitor.convert(monitor, ExpandWork);
		sub.setTaskName(Messages.Director_Task_Resolving_Dependencies);
		try {
			MultiStatus result = new MultiStatus(DirectorActivator.PI_DIRECTOR, 1, Messages.Director_Revert_Problems, null);

			if (!Boolean.valueOf(profileSnapshot.getProperty(IInstallableUnit.PROP_TYPE_PROFILE)).booleanValue()) {
				result.add(new Status(IStatus.ERROR, DirectorActivator.PI_DIRECTOR, NLS.bind(Messages.Director_Unexpected_IU, profileSnapshot.getId())));
				return new ProvisioningPlan(result);
			}
			IProfile profile = getProfile(profileSnapshot.getId());
			if (profile == null) {
				result.add(new Status(IStatus.ERROR, DirectorActivator.PI_DIRECTOR, NLS.bind(Messages.Director_Unexpected_IU, profileSnapshot.getId())));
				return new ProvisioningPlan(result);
			}

			//TODO if the profile changes (locations are being modified, etc), should not we do a full uninstall then an install?
			//Maybe it depends on the kind of changes in a profile
			//We need to get all the ius that were part of the profile and give that to be what to become

			Dictionary snapshotSelectionContext = createSelectionContext(getSnapshotProperties(profileSnapshot));
			IInstallableUnit[] availableIUs = gatherAvailableInstallableUnits(new IInstallableUnit[] {profileSnapshot}, context.getMetadataRepositories(), context, sub.newChild(ExpandWork / 2));
			NewDependencyExpander toExpander = new NewDependencyExpander(new IInstallableUnit[] {profileSnapshot}, null, availableIUs, snapshotSelectionContext, true);
			toExpander.expand(sub.newChild(ExpandWork / 2));
			ResolutionHelper newStateHelper = new ResolutionHelper(snapshotSelectionContext, toExpander.getRecommendations());
			Collection newState = newStateHelper.attachCUs(toExpander.getAllInstallableUnits());
			newState.remove(profileSnapshot);

			Collection oldIUs = new HashSet();
			for (Iterator it = profile.query(InstallableUnitQuery.ANY, new Collector(), null).iterator(); it.hasNext();) {
				oldIUs.add(it.next());
			}

			Dictionary oldSelectionContext = createSelectionContext(profile.getProperties());
			ResolutionHelper oldStateHelper = new ResolutionHelper(oldSelectionContext, null);
			Collection oldState = oldStateHelper.attachCUs(oldIUs);
			ProfileChangeRequest profileChangeRequest = generateChangeRequest(profile, profileSnapshot, newState);
			return generateProvisioningPlan(null, oldState, newState, oldStateHelper.getSorted(), newStateHelper.getSorted(), profileChangeRequest);
		} finally {
			sub.done();
		}
	}

	private Dictionary createSelectionContext(Map properties) {
		Hashtable result = new Hashtable(properties);
		String environments = (String) properties.get(IProfile.PROP_ENVIRONMENTS);
		if (environments == null)
			return result;
		for (StringTokenizer tokenizer = new StringTokenizer(environments, ","); tokenizer.hasMoreElements();) { //$NON-NLS-1$
			String entry = tokenizer.nextToken();
			int i = entry.indexOf('=');
			String key = entry.substring(0, i).trim();
			String value = entry.substring(i + 1).trim();
			result.put(key, value);
		}
		return result;
	}

	private Map getSnapshotProperties(IInstallableUnit profileSnapshot) {
		Map result = new HashMap();
		for (Iterator it = profileSnapshot.getProperties().entrySet().iterator(); it.hasNext();) {
			Entry entry = (Entry) it.next();
			String key = (String) entry.getKey();
			if (IInstallableUnit.PROP_TYPE_PROFILE.equals(key) || key.startsWith(FormerState.IUPROP_PREFIX))
				continue;

			result.put(key, entry.getValue());
		}
		return result;
	}

	// TODO note that this only describes property changes, not the IU changes.
	private ProfileChangeRequest generateChangeRequest(IProfile profile, IInstallableUnit iuDescribingNewState, Collection newIUs) {
		ProfileChangeRequest request = new ProfileChangeRequest(profile);
		Map profileProperties = iuDescribingNewState.getProperties();
		for (Iterator iter = profileProperties.keySet().iterator(); iter.hasNext();) {
			String key = (String) iter.next();
			// ignore the property that confirms this IU is a profile snapshot
			if (IInstallableUnit.PROP_TYPE_PROFILE.equals(key))
				continue;
			if (key.startsWith(FormerState.IUPROP_PREFIX)) {
				int postID = key.indexOf(FormerState.IUPROP_POSTFIX, FormerState.IUPROP_PREFIX.length());
				String id = key.substring(FormerState.IUPROP_PREFIX.length(), postID);
				for (Iterator iuIter = newIUs.iterator(); iuIter.hasNext();) {
					IInstallableUnit iu = (IInstallableUnit) iuIter.next();
					if (id.equals(iu.getId())) {
						String iuPropKey = key.substring(postID + FormerState.IUPROP_POSTFIX.length());
						request.setInstallableUnitProfileProperty(iu, iuPropKey, profileProperties.get(key));
						continue;
					}
				}
			} else {
				request.setProfileProperty(key, profileProperties.get(key));
			}
		}
		// Now process removals, but don't include those that simply changed or were otherwise reset above.
		for (Iterator iter = profile.getProperties().keySet().iterator(); iter.hasNext();) {
			String key = (String) iter.next();
			if (!request.getPropertiesToAdd().containsKey(key))
				request.removeProfileProperty(key);
		}
		IInstallableUnit[] ius = getInstallableUnits(profile);
		for (int i = 0; i < ius.length; i++) {
			// Get the properties we added so those can be excluded
			Iterator iuIter = request.getInstallableUnitProfilePropertiesToAdd().keySet().iterator();
			HashMap addedProperties = new HashMap();
			while (iuIter.hasNext()) {
				IInstallableUnit iu = (IInstallableUnit) iuIter.next();
				if (iu.getId().equals(ius[i].getId())) {
					addedProperties = (HashMap) request.getInstallableUnitProfilePropertiesToAdd().get(iu);
					continue;
				}
			}

			for (Iterator iter = profile.getInstallableUnitProperties(ius[i]).keySet().iterator(); iter.hasNext();) {
				String key = (String) iter.next();
				if (!addedProperties.containsKey(key))
					request.removeInstallableUnitProfileProperty(ius[i], key);
			}
		}

		return request;
	}

	protected IInstallableUnit[] gatherAvailableInstallableUnits(IInstallableUnit[] additionalSource, URL[] repositories, ProvisioningContext context, IProgressMonitor monitor) {
		Map resultsMap = new HashMap();
		if (additionalSource != null) {
			for (int i = 0; i < additionalSource.length; i++) {
				String key = additionalSource[i].getId() + "_" + additionalSource[i].getVersion().toString(); //$NON-NLS-1$
				resultsMap.put(key, additionalSource[i]);
			}
		}
		if (context != null) {
			for (Iterator iter = context.getExtraIUs().iterator(); iter.hasNext();) {
				IInstallableUnit iu = (IInstallableUnit) iter.next();
				String key = iu.getId() + '_' + iu.getVersion().toString();
				resultsMap.put(key, iu);
			}
		}

		IMetadataRepositoryManager repoMgr = (IMetadataRepositoryManager) ServiceHelper.getService(DirectorActivator.context, IMetadataRepositoryManager.class.getName());
		if (repositories == null)
			repositories = repoMgr.getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);

		SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 200);
		for (int i = 0; i < repositories.length; i++) {
			try {
				IMetadataRepository repository = repoMgr.loadRepository(repositories[i], sub.newChild(100));
				Collector matches = repository.query(new InstallableUnitQuery(null, VersionRange.emptyRange), new Collector(), sub.newChild(100));
				for (Iterator it = matches.iterator(); it.hasNext();) {
					IInstallableUnit iu = (IInstallableUnit) it.next();
					String key = iu.getId() + "_" + iu.getVersion().toString(); //$NON-NLS-1$
					IInstallableUnit currentIU = (IInstallableUnit) resultsMap.get(key);
					if (currentIU == null || hasHigherFidelity(iu, currentIU))
						resultsMap.put(key, iu);
				}
			} catch (ProvisionException e) {
				//skip unreadable repositories
			}
		}
		sub.done();
		Collection results = resultsMap.values();
		return (IInstallableUnit[]) results.toArray(new IInstallableUnit[results.size()]);
	}

	private boolean hasHigherFidelity(IInstallableUnit iu, IInstallableUnit currentIU) {
		if (Boolean.valueOf(currentIU.getProperty(IInstallableUnit.PROP_PARTIAL_IU)).booleanValue() && !Boolean.valueOf(iu.getProperty(IInstallableUnit.PROP_PARTIAL_IU)).booleanValue())
			return true;
		return false;
	}

	public ProvisioningPlan getProvisioningPlan(ProfileChangeRequest profileChangeRequest, ProvisioningContext context, IProgressMonitor monitor) {
		SubMonitor sub = SubMonitor.convert(monitor, ExpandWork);
		sub.setTaskName(Messages.Director_Task_Resolving_Dependencies);
		try {
			IProfile profile = profileChangeRequest.getProfile();

			IInstallableUnit[] allIUs = updatePlannerInfo(profileChangeRequest);

			URL[] metadataRepositories = (context != null) ? context.getMetadataRepositories() : null;
			Dictionary newSelectionContext = createSelectionContext(profileChangeRequest.getProfileProperties());

			List extraIUs = new ArrayList(Arrays.asList(profileChangeRequest.getAddedInstallableUnits()));
			extraIUs.addAll(Arrays.asList(profileChangeRequest.getRemovedInstallableUnits()));
			extraIUs.addAll(profileChangeRequest.getProfile().query(InstallableUnitQuery.ANY, new Collector(), null).toCollection());

			IInstallableUnit[] availableIUs = gatherAvailableInstallableUnits((IInstallableUnit[]) extraIUs.toArray(new IInstallableUnit[extraIUs.size()]), metadataRepositories, context, sub.newChild(ExpandWork / 4));

			Slicer slicer = new Slicer(allIUs, availableIUs, newSelectionContext);
			IQueryable slice = slicer.slice(allIUs, monitor);
			if (slice == null)
				return new ProvisioningPlan(slicer.getStatus());
			Projector projector = new Projector(slice, newSelectionContext);
			projector.encode(allIUs, sub.newChild(ExpandWork / 4));
			IStatus s = projector.invokeSolver(sub.newChild(ExpandWork / 4));

			if (s.getSeverity() == IStatus.ERROR) {
				//log the error from the new solver so it is not lost
				LogHelper.log(s);
				if (!"true".equalsIgnoreCase(context == null ? null : context.getProperty("org.eclipse.equinox.p2.disable.error.reporting"))) {
					//We invoke the old resolver to get explanations for now
					IStatus oldResolverStatus = new NewDependencyExpander(allIUs, null, availableIUs, newSelectionContext, false).expand(sub.newChild(ExpandWork / 4));
					if (!oldResolverStatus.isOK())
						s = oldResolverStatus;
				}
				return new ProvisioningPlan(s);
			}
			Collection newState = projector.extractSolution();

			ResolutionHelper newStateHelper = new ResolutionHelper(newSelectionContext, null);
			newState = newStateHelper.attachCUs(newState);

			ResolutionHelper oldStateHelper = new ResolutionHelper(createSelectionContext(profile.getProperties()), null);
			Collection oldState = oldStateHelper.attachCUs(profile.query(InstallableUnitQuery.ANY, new Collector(), null).toCollection());

			return generateProvisioningPlan(s, oldState, newState, oldStateHelper.getSorted(), newStateHelper.getSorted(), profileChangeRequest);
		} finally {
			sub.done();
		}
	}

	//The planner uses installable unit properties to keep track of what it has been asked to install. This updates this information
	private IInstallableUnit[] updatePlannerInfo(ProfileChangeRequest profileChangeRequest) {
		Collector alreadyInstalled = profileChangeRequest.getProfile().query(new IUProfilePropertyQuery(profileChangeRequest.getProfile(), PLANNER_MARKER, Boolean.toString(true)), new Collector(), null);

		IInstallableUnit[] added = profileChangeRequest.getAddedInstallableUnits();
		IInstallableUnit[] removed = profileChangeRequest.getRemovedInstallableUnits();
		IInstallableUnit[] allIUs = new IInstallableUnit[alreadyInstalled.size() + added.length + removed.length];

		int count = 0;
		for (Iterator iterator = alreadyInstalled.iterator(); iterator.hasNext();) {
			IInstallableUnit iu = (IInstallableUnit) iterator.next();
			boolean found = false;
			for (int i = 0; i < removed.length; i++) {
				if (iu.equals(removed[i])) {
					profileChangeRequest.removeInstallableUnitProfileProperty(removed[i], PLANNER_MARKER);
					found = true;
					break;
				}
			}
			if (!found)
				allIUs[count++] = iu;
		}
		for (int i = 0; i < added.length; i++) {
			allIUs[count++] = added[i];
			profileChangeRequest.setInstallableUnitProfileProperty(added[i], PLANNER_MARKER, "true"); //$NON-NLS-1$
		}
		if (allIUs.length > count) {
			IInstallableUnit[] result = new IInstallableUnit[count];
			System.arraycopy(allIUs, 0, result, 0, count);
			allIUs = result;
		}
		return allIUs;
	}

	public IInstallableUnit[] updatesFor(IInstallableUnit toUpdate, ProvisioningContext context, IProgressMonitor monitor) {
		Map resultsMap = new HashMap();

		IMetadataRepositoryManager repoMgr = (IMetadataRepositoryManager) ServiceHelper.getService(DirectorActivator.context, IMetadataRepositoryManager.class.getName());
		URL[] repositories = context.getMetadataRepositories();
		if (repositories == null)
			repositories = repoMgr.getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);

		SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 200);
		for (int i = 0; i < repositories.length; i++) {
			try {
				IMetadataRepository repository = repoMgr.loadRepository(repositories[i], sub.newChild(100));
				Collector matches = repository.query(new UpdateQuery(toUpdate), new Collector(), sub.newChild(100));
				for (Iterator it = matches.iterator(); it.hasNext();) {
					IInstallableUnit iu = (IInstallableUnit) it.next();
					String key = iu.getId() + "_" + iu.getVersion().toString(); //$NON-NLS-1$
					IInstallableUnit currentIU = (IInstallableUnit) resultsMap.get(key);
					if (currentIU == null || hasHigherFidelity(iu, currentIU))
						resultsMap.put(key, iu);
				}
			} catch (ProvisionException e) {
				//skip unreadable repositories
			}
		}
		sub.done();
		Collection results = resultsMap.values();
		return (IInstallableUnit[]) results.toArray(new IInstallableUnit[results.size()]);
	}
}
