/*******************************************************************************
 * Copyright (c) 2007, 2018 IBM Corporation and others.
 *
 * This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License 2.0 which accompanies this distribution, and is
 * available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    IBM Corporation - initial API and implementation
 *    Cloudsmith Inc. - query indexes
 *
 ******************************************************************************/
package org.eclipse.equinox.internal.p2.engine;

import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
import org.eclipse.equinox.internal.p2.metadata.*;
import org.eclipse.equinox.internal.p2.metadata.index.*;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.KeyWithLocale;
import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext;
import org.eclipse.equinox.p2.metadata.expression.IExpression;
import org.eclipse.equinox.p2.metadata.index.IIndex;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.osgi.util.NLS;

public class Profile extends IndexProvider<IInstallableUnit> implements IProfile {

	/**
	 * An index that limits the candidates to those units that has profile properties
	 */
	class ProfilePropertyIndex implements IIndex<IInstallableUnit> {
		@Override
		public Iterator<IInstallableUnit> getCandidates(IEvaluationContext ctx, IExpression variable, IExpression booleanExpr) {
			return iuProperties.keySet().iterator();
		}
	}

	private final IProvisioningAgent agent;
	//Internal id of the profile
	private final String profileId;

	private Profile parentProfile;

	private IIndex<IInstallableUnit> idIndex;

	private IIndex<IInstallableUnit> propertiesIndex;

	private IIndex<IInstallableUnit> capabilityIndex;

	private TranslationSupport translationSupport;

	/**
	 * 	A collection of child profiles.
	 */
	private List<String> subProfileIds; // child profile ids

	/**
	 * This storage is to be used by the touchpoints to store data.
	 */
	private OrderedProperties storage = new OrderedProperties();

	private IUMap ius = new IUMap();
	final Map<IInstallableUnit, OrderedProperties> iuProperties = new HashMap<>();
	private boolean changed = false;

	private long timestamp;
	private ISurrogateProfileHandler surrogateProfileHandler;

	public Profile(IProvisioningAgent agent, String profileId, Profile parent, Map<String, String> properties) {
		this.agent = agent;
		if (profileId == null || profileId.length() == 0) {
			throw new IllegalArgumentException(NLS.bind(Messages.Profile_Null_Profile_Id, null));
		}
		this.profileId = profileId;
		setParent(parent);
		if (properties != null)
			storage.putAll(properties);

	}

	@Override
	public String getProfileId() {
		return profileId;
	}

	public IProfile getParentProfile() {
		return parentProfile;
	}

	public void setParent(Profile profile) {
		if (profile == parentProfile)
			return;

		if (parentProfile != null)
			parentProfile.removeSubProfile(profileId);

		parentProfile = profile;
		if (parentProfile != null)
			parentProfile.addSubProfile(profileId);
	}

	/*
	 * 	A profile is a root profile if it is not a sub-profile
	 * 	of another profile.
	 */
	public boolean isRootProfile() {
		return parentProfile == null;
	}

	public void addSubProfile(String subProfileId) throws IllegalArgumentException {
		if (subProfileIds == null)
			subProfileIds = new ArrayList<>();

		if (!subProfileIds.contains(subProfileId))
			subProfileIds.add(subProfileId);

		//		if (!subProfileIds.add(subProfileId))
		//			throw new IllegalArgumentException(NLS.bind(Messages.Profile_Duplicate_Child_Profile_Id, new String[] {subProfileId, this.getProfileId()}));
	}

	public void removeSubProfile(String subProfileId) throws IllegalArgumentException {
		if (subProfileIds != null)
			subProfileIds.remove(subProfileId);
	}

	public boolean hasSubProfiles() {
		return subProfileIds != null && !subProfileIds.isEmpty();
	}

	public List<String> getSubProfileIds() {
		if (subProfileIds == null)
			return Collections.emptyList();
		return Collections.unmodifiableList(subProfileIds);
	}

	@Override
	public String getProperty(String key) {
		String value = getLocalProperty(key);
		if (value == null && parentProfile != null) {
			value = parentProfile.getProperty(key);
		}
		return value;
	}

	public String getLocalProperty(String key) {
		return storage.getProperty(key);
	}

	/**
	 * 	Associate the given value with the given key
	 * 	in the local storage of this profile.
	 */
	public void setProperty(String key, String value) {
		storage.setProperty(key, value);
		changed = true;
	}

	public void removeProperty(String key) {
		storage.remove(key);
		changed = true;
	}

	@Override
	public synchronized IIndex<IInstallableUnit> getIndex(String memberName) {
		if (InstallableUnit.MEMBER_ID.equals(memberName)) {
			if (idIndex == null)
				idIndex = new IdIndex(ius);
			return idIndex;
		}

		if (InstallableUnit.MEMBER_PROVIDED_CAPABILITIES.equals(memberName)) {
			if (capabilityIndex == null)
				capabilityIndex = new CapabilityIndex(ius.iterator());
			return capabilityIndex;
		}

		if (InstallableUnit.MEMBER_PROFILE_PROPERTIES.equals(memberName)) {
			if (propertiesIndex == null)
				propertiesIndex = new ProfilePropertyIndex();
			return propertiesIndex;
		}
		return null;
	}

	@Override
	public Iterator<IInstallableUnit> everything() {
		return ius.iterator();
	}

	@Override
	public Object getManagedProperty(Object client, String memberName, Object key) {
		if (!(client instanceof IInstallableUnit))
			return null;
		IInstallableUnit iu = (IInstallableUnit) client;
		if (InstallableUnit.MEMBER_PROFILE_PROPERTIES.equals(memberName) && key instanceof String)
			return getInstallableUnitProperty(iu, (String) key);
		if (InstallableUnit.MEMBER_TRANSLATED_PROPERTIES.equals(memberName)) {
			synchronized (this) {
				if (translationSupport == null)
					translationSupport = new TranslationSupport(this);
				return key instanceof KeyWithLocale ? translationSupport.getIUProperty(iu, (KeyWithLocale) key) : translationSupport.getIUProperty(iu, key.toString());
			}
		}
		return null;
	}

	@Override
	public IQueryResult<IInstallableUnit> available(IQuery<IInstallableUnit> query, IProgressMonitor monitor) {
		if (surrogateProfileHandler != null)
			return surrogateProfileHandler.queryProfile(this, query, monitor);
		return query(query, new NullProgressMonitor());
	}

	@Override
	public String getInstallableUnitProperty(IInstallableUnit iu, String key) {
		OrderedProperties properties = iuProperties.get(iu);
		if (properties == null)
			return null;

		return properties.getProperty(key);
	}

	public String setInstallableUnitProperty(IInstallableUnit iu, String key, String value) {
		//		String iuKey = createIUKey(iu);
		OrderedProperties properties = iuProperties.get(iu);
		if (properties == null) {
			properties = new OrderedProperties();
			iuProperties.put(iu, properties);
		}

		changed = true;
		return (String) properties.setProperty(key, value);
	}

	public String removeInstallableUnitProperty(IInstallableUnit iu, String key) {
		//		String iuKey = createIUKey(iu);
		OrderedProperties properties = iuProperties.get(iu);
		if (properties == null)
			return null;

		String oldValue = properties.remove(key);
		if (properties.isEmpty())
			iuProperties.remove(iu);

		changed = true;
		return oldValue;
	}

	//	private static String createIUKey(IInstallableUnit iu) {
	//		return iu.getId() + "_" + iu.getVersion().toString(); //$NON-NLS-1$
	//	}

	public Map<String, String> getLocalProperties() {
		return OrderedProperties.unmodifiableProperties(storage);
	}

	@Override
	public Map<String, String> getProperties() {
		if (parentProfile == null)
			return getLocalProperties();

		Map<String, String> properties = new HashMap<>(parentProfile.getProperties());
		properties.putAll(storage);
		return OrderedProperties.unmodifiableProperties(properties);
	}

	@Override
	public IProvisioningAgent getProvisioningAgent() {
		return agent;
	}

	/**
	 * 	Add all the properties in the map to the local properties
	 * 	of the profile.
	 */
	public void addProperties(Map<String, String> properties) {
		storage.putAll(properties);
		changed = true;
	}

	public void addInstallableUnit(IInstallableUnit iu) {
		iu = iu.unresolved();
		if (ius.contains(iu))
			return;

		ius.add(iu);
		changed = true;
	}

	public void removeInstallableUnit(IInstallableUnit iu) {
		iu = iu.unresolved();
		ius.remove(iu);
		changed = true;
	}

	@Override
	public Map<String, String> getInstallableUnitProperties(IInstallableUnit iu) {
		OrderedProperties properties = iuProperties.get(iu);
		if (properties == null)
			properties = new OrderedProperties();

		return OrderedProperties.unmodifiableProperties(properties);
	}

	public void clearLocalProperties() {
		storage.clear();
		changed = true;
	}

	public boolean isChanged() {
		return changed;
	}

	public void setChanged(boolean isChanged) {
		changed = isChanged;
	}

	public void clearInstallableUnits() {
		ius.clear();
		iuProperties.clear();
		changed = true;
	}

	public Profile snapshot() {
		Profile parentSnapshot = null;
		if (parentProfile != null)
			parentSnapshot = parentProfile.snapshot();

		Profile snapshot = new Profile(agent, profileId, parentSnapshot, storage);
		if (surrogateProfileHandler != null)
			snapshot.setSurrogateProfileHandler(surrogateProfileHandler);
		snapshot.setTimestamp(timestamp);

		if (subProfileIds != null) {
			for (String subProfileId : subProfileIds) {
				snapshot.addSubProfile(subProfileId);
			}
		}

		for (Iterator<IInstallableUnit> iter = ius.iterator(); iter.hasNext();) {
			IInstallableUnit iu = iter.next();
			snapshot.addInstallableUnit(iu);
			Map<String, String> properties = getInstallableUnitProperties(iu);
			if (properties != null)
				snapshot.addInstallableUnitProperties(iu, properties);
		}
		snapshot.setChanged(false);
		return snapshot;
	}

	public void addInstallableUnitProperties(IInstallableUnit iu, Map<String, String> properties) {
		for (Entry<String, String> entry : properties.entrySet()) {
			setInstallableUnitProperty(iu, entry.getKey(), entry.getValue());
		}
	}

	public void clearInstallableUnitProperties(IInstallableUnit iu) {
		iuProperties.remove(iu);
		changed = true;
	}

	public void clearOrphanedInstallableUnitProperties() {
		Set<IInstallableUnit> keys = iuProperties.keySet();
		//		Set orphans = new HashSet();
		Collection<IInstallableUnit> toRemove = new ArrayList<>();
		for (IInstallableUnit iu : keys) {
			if (!ius.contains(iu))
				toRemove.add(iu);
		}

		for (IInstallableUnit iu : toRemove) {
			iuProperties.remove(iu);
		}
		//		List iuKeys = new ArrayList();
		//		for (Iterator it = ius.iterator(); it.hasNext();)
		//			iuKeys.add((IInstallableUnit) it.next());
		//
		//		iuProperties.keySet().retainAll(iuKeys);
	}

	@Override
	public long getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(long millis) {
		timestamp = millis;
	}

	public void setSurrogateProfileHandler(ISurrogateProfileHandler surrogateProfileHandler) {
		this.surrogateProfileHandler = surrogateProfileHandler;
	}

	/**
	 * Prints a string representation for debugging purposes only.
	 */
	@Override
	public String toString() {
		return "Profile(" + getProfileId() + ", timestamp: " + getTimestamp() + ')'; //$NON-NLS-1$ //$NON-NLS-2$
	}
}
