/*******************************************************************************
 * Copyright (c) 2000, 2015 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 - Initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.internal.build.site;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.p2.publisher.eclipse.Feature;
import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.build.*;
import org.eclipse.pde.internal.build.site.compatibility.FeatureReference;
import org.osgi.framework.Filter;
import org.osgi.framework.Version;

/**
 * This site represent a site at build time. A build time site is made of code
 * to compile, and a potential installation of eclipse (or derived products)
 * against which the code must be compiled. Moreover this site provide access to
 * a pluginRegistry.
 */
public class BuildTimeSite /*extends Site*/implements IPDEBuildConstants, IXMLConstants {
	private final BuildTimeFeatureFactory factory = new BuildTimeFeatureFactory();
	private final Map<String, Set<BuildTimeFeature>> featureCache = new HashMap<String, Set<BuildTimeFeature>>();
	private final Map<URL, BuildTimeFeature> featureURLCache = new HashMap<URL, BuildTimeFeature>();
	private List<FeatureReference> featureReferences;
	private BuildTimeSiteContentProvider contentProvider;
	private boolean featuresResolved = false;

	private PDEState state;
	private Properties repositoryVersions; //version for the features
	private boolean reportResolutionErrors;
	private Properties platformProperties;
	private String[] eeSources;

	//Support for filtering what is added to the state
	private List<String> rootFeaturesForFilter;
	private List<String> rootPluginsForFiler;
	private boolean filter = false;

	private final Comparator<Feature> featureComparator = new Comparator<Feature>() {
		// Sort highest to lowest version, they are assumed to have the same id
		@Override
		public int compare(Feature arg0, Feature arg1) {
			Version v0 = new Version(arg0.getVersion());
			Version v1 = new Version(arg1.getVersion());
			return -1 * v0.compareTo(v1);
		}
	};

	public void setReportResolutionErrors(boolean value) {
		reportResolutionErrors = value;
	}

	public void setPlatformPropeties(Properties platformProperties) {
		this.platformProperties = platformProperties;
	}

	public Properties getFeatureVersions() {
		if (repositoryVersions == null) {
			repositoryVersions = new Properties();
			try {
				InputStream input = new BufferedInputStream(new FileInputStream(AbstractScriptGenerator.getWorkingDirectory() + '/' + DEFAULT_FEATURE_REPOTAG_FILENAME_DESCRIPTOR));
				try {
					repositoryVersions.load(input);
				} finally {
					input.close();
				}
			} catch (IOException e) {
				//Ignore
			}
		}
		return repositoryVersions;
	}

	private Properties getUIPlatformProperties() {
		Properties result = new Properties();
		result.put(IPDEBuildConstants.PROPERTY_RESOLVE_OPTIONAL, IBuildPropertiesConstants.TRUE);
		result.put(IPDEBuildConstants.PROPERTY_RESOLVER_MODE, IPDEBuildConstants.VALUE_DEVELOPMENT);
		return result;
	}

	private Collection<File> removeDuplicates(Collection<File> bundles) {
		Set<File> result = new LinkedHashSet<File>(bundles.size() / 2);
		for (Iterator<File> iterator = bundles.iterator(); iterator.hasNext();) {
			File bundle = iterator.next();
			try {
				bundle = bundle.getCanonicalFile();
			} catch (IOException e) {
				// ignore
			}
			if (result.contains(bundle))
				continue;
			result.add(bundle);
		}
		return result;
	}

	public PDEState getRegistry() throws CoreException {
		if (state == null) {
			// create the registry according to the site where the code to
			// compile is, and a existing installation of eclipse
			BuildTimeSiteContentProvider provider = getSiteContentProvider();

			if (provider.getInitialState() != null) {
				state = new PDEState(provider.getInitialState());
				state.setEESources(eeSources);
				state.setPlatformProperties(getUIPlatformProperties());
				state.resolveState();
				return state;
			}

			if (filter) {
				state = new FilteringState();
				((FilteringState) state).setFilter(findAllReferencedPlugins());
			} else {
				state = new PDEState();
			}
			if (platformProperties != null)
				state.setPlatformProperties(platformProperties);

			Collection<File> bundles = removeDuplicates(provider.getPluginPaths());
			state.addBundles(bundles);
			state.setEESources(eeSources);

			//Once all the elements have been added to the state, the filter is removed to allow for the generated plug-ins to be added
			if (state instanceof FilteringState) {
				((FilteringState) state).setFilter(null);
			}
			state.resolveState();
			BundleDescription[] allBundles = state.getState().getBundles();
			BundleDescription[] resolvedBundles = state.getState().getResolvedBundles();
			if (allBundles.length == resolvedBundles.length)
				return state;

			if (reportResolutionErrors) {
				MultiStatus errors = new MultiStatus(IPDEBuildConstants.PI_PDEBUILD, 1, Messages.exception_registryResolution, null);
				BundleDescription[] all = state.getState().getBundles();
				StateHelper helper = Platform.getPlatformAdmin().getStateHelper();
				for (int i = 0; i < all.length; i++) {
					if (!all[i].isResolved()) {
						ResolverError[] resolutionErrors = state.getState().getResolverErrors(all[i]);
						VersionConstraint[] versionErrors = helper.getUnsatisfiedConstraints(all[i]);

						//ignore problems when they are caused by bundles not being built for the right config
						if (isConfigError(all[i], resolutionErrors, AbstractScriptGenerator.getConfigInfos()))
							continue;

						String errorMessage = "Bundle " + all[i].getSymbolicName() + ":\n" + getResolutionErrorMessage(resolutionErrors); //$NON-NLS-1$ //$NON-NLS-2$
						for (int j = 0; j < versionErrors.length; j++) {
							errorMessage += '\t' + getResolutionFailureMessage(versionErrors[j]) + '\n';
						}
						errors.add(new Status(IStatus.WARNING, IPDEBuildConstants.PI_PDEBUILD, IStatus.WARNING, errorMessage, null));
					}
				}
				if (errors.getChildren().length > 0)
					BundleHelper.getDefault().getLog().log(errors);
			}
		}
		if (!state.getState().isResolved())
			state.state.resolve(true);
		return state;
	}

	public IStatus missingPlugin(String id, String version, Feature containingFeature, boolean throwException) throws CoreException {
		BundleDescription bundle = state.getBundle(id, version, false);
		if (bundle == null) {
			String message = NLS.bind(Messages.exception_missingPlugin, id + "_" + version); //$NON-NLS-1$
			if (containingFeature != null)
				message = NLS.bind(Messages.includedFromFeature, containingFeature.getId(), message);
			IStatus status = new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message, null);
			if (throwException)
				throw new CoreException(status);
			return status;
		}

		//we expect this bundle to not be resolved, but just in case...
		if (bundle.isResolved())
			return null;

		ResolverError[] resolutionErrors = state.getState().getResolverErrors(bundle);
		return missingPlugin(bundle, resolutionErrors, containingFeature, throwException);
	}

	public static IStatus missingPlugin(BundleDescription bundle, ResolverError[] resolutionErrors, Feature containingFeature, boolean throwException) throws CoreException {
		StateHelper helper = Platform.getPlatformAdmin().getStateHelper();
		VersionConstraint[] versionErrors = helper.getUnsatisfiedConstraints(bundle);

		String message = NLS.bind(Messages.exception_unresolvedPlugin, bundle.getSymbolicName() + '_' + bundle.getVersion().toString());
		if (containingFeature != null)
			message = NLS.bind(Messages.includedFromFeature, containingFeature.getId(), message);
		message += ":\n" + BuildTimeSite.getResolutionErrorMessage(resolutionErrors); //$NON-NLS-1$
		for (int j = 0; j < versionErrors.length; j++) {
			message += '\t' + BuildTimeSite.getResolutionFailureMessage(versionErrors[j]) + '\n';
		}

		IStatus status = new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message, null);
		if (throwException)
			throw new CoreException(status);
		return status;
	}

	//Return whether the resolution error is caused because we are not building for the proper configurations.
	static public boolean isConfigError(BundleDescription bundle, ResolverError[] errors, List<Config> configs) {
		Dictionary<String, String> environment = new Hashtable<String, String>(3);
		Filter bundleFilter = BundleHelper.getDefault().getFilter(bundle);
		if (bundleFilter != null && hasPlatformFilterError(errors) != null) {
			for (Iterator<Config> iter = configs.iterator(); iter.hasNext();) {
				Config aConfig = iter.next();
				environment.put("osgi.os", aConfig.getOs()); //$NON-NLS-1$
				environment.put("osgi.ws", aConfig.getWs()); //$NON-NLS-1$
				environment.put("osgi.arch", aConfig.getArch()); //$NON-NLS-1$
				if (bundleFilter.match(environment)) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	//Check if the set of errors contain a platform filter
	static private ResolverError hasPlatformFilterError(ResolverError[] errors) {
		for (int i = 0; i < errors.length; i++) {
			if ((errors[i].getType() & ResolverError.PLATFORM_FILTER) != 0)
				return errors[i];
			if ((errors[i].getType() & ResolverError.NO_NATIVECODE_MATCH) != 0)
				return errors[i];
		}
		return null;
	}

	static public String getResolutionErrorMessage(ResolverError[] errors) {
		String errorMessage = ""; //$NON-NLS-1$
		for (int i = 0; i < errors.length; i++) {
			if ((errors[i].getType() & (ResolverError.SINGLETON_SELECTION | ResolverError.FRAGMENT_CONFLICT | ResolverError.IMPORT_PACKAGE_USES_CONFLICT | ResolverError.REQUIRE_BUNDLE_USES_CONFLICT | ResolverError.MISSING_EXECUTION_ENVIRONMENT)) != 0)
				errorMessage += '\t' + errors[i].toString() + '\n';
		}
		return errorMessage;
	}

	static public String getResolutionFailureMessage(VersionConstraint unsatisfied) {
		if (unsatisfied.isResolved())
			throw new IllegalArgumentException();
		if (unsatisfied instanceof ImportPackageSpecification)
			return NLS.bind(Messages.unsatisfied_import, displayVersionConstraint(unsatisfied));
		if (unsatisfied instanceof NativeCodeSpecification)
			return NLS.bind(Messages.unsatisfied_nativeSpec, unsatisfied.toString());
		if (unsatisfied instanceof BundleSpecification) {
			if (((BundleSpecification) unsatisfied).isOptional())
				return NLS.bind(Messages.unsatisfied_optionalBundle, displayVersionConstraint(unsatisfied));
			return NLS.bind(Messages.unsatisfied_required, displayVersionConstraint(unsatisfied));
		}
		return NLS.bind(Messages.unsatisfied_host, displayVersionConstraint(unsatisfied));
	}

	static private String displayVersionConstraint(VersionConstraint constraint) {
		VersionRange versionSpec = constraint.getVersionRange();
		if (versionSpec == null)
			return constraint.getName();
		return constraint.getName() + '_' + versionSpec;
	}

	public BuildTimeFeature findFeature(String featureId, String versionId, boolean throwsException) throws CoreException {
		VersionRange range = Utils.createVersionRange(versionId);
		return findFeature(featureId, range, throwsException);
	}

	private BuildTimeFeature findFeature(String featureId, VersionRange range, boolean throwsException) throws CoreException {
		if (range == null)
			range = VersionRange.emptyRange;

		if (!featuresResolved)
			resolveFeatureReferences();

		if (featureCache.containsKey(featureId)) {
			//Set is ordered highest version to lowest, return the first that matches the range
			Set<BuildTimeFeature> featureSet = featureCache.get(featureId);
			for (Iterator<BuildTimeFeature> iterator = featureSet.iterator(); iterator.hasNext();) {
				BuildTimeFeature feature = iterator.next();
				Version featureVersion = new Version(feature.getVersion());
				if (range.isIncluded(featureVersion)) {
					return feature;
				}
			}
		}

		if (throwsException) {
			String message = null;
			if (range.equals(VersionRange.emptyRange))
				message = NLS.bind(Messages.exception_missingFeature, featureId);
			else
				message = NLS.bind(Messages.exception_missingFeatureInRange, featureId, range);
			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_FEATURE_MISSING, message, null));
		}

		return null;
	}

	private void resolveFeatureReferences() {
		FeatureReference[] features = getFeatureReferences();
		for (int i = 0; i < features.length; i++) {
			try {
				//getting the feature for the first time will result in it being added to featureCache
				features[i].getFeature();
			} catch (CoreException e) {
				// just log the exception, but do not re-throw it - let other features to be resolved 
				String message = NLS.bind(Messages.exception_featureParse, features[i].getURL());
				IStatus status = new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_FEATURE_MISSING, message, e);
				BundleHelper.getDefault().getLog().log(status);
			}
		}
		featuresResolved = true;
	}

	public void addFeatureReferenceModel(File featureXML) {
		URL featureURL;
		FeatureReference featureRef;
		if (featureXML.exists()) {
			// Here we could not use toURL() on currentFeatureDir, because the
			// URL has a slash after the colons (file:/c:/foo) whereas the
			// plugins don't
			// have it (file:d:/eclipse/plugins) and this causes problems later
			// to compare URLs... and compute relative paths
			try {
				featureURL = new URL("file:" + featureXML.getAbsolutePath() + '/'); //$NON-NLS-1$
				featureRef = new FeatureReference();
				featureRef.setSiteModel(this);
				featureRef.setURLString(featureURL.toExternalForm());
				addFeatureReferenceModel(featureRef);
			} catch (MalformedURLException e) {
				BundleHelper.getDefault().getLog().log(new Status(IStatus.WARNING, PI_PDEBUILD, WARNING_MISSING_SOURCE, NLS.bind(Messages.warning_cannotLocateSource, featureXML.getAbsolutePath()), e));
			}
		}
	}

	public void addFeatureReferenceModel(FeatureReference featureReference) {
		if (this.featureReferences == null)
			this.featureReferences = new ArrayList<FeatureReference>();

		this.featureReferences.add(featureReference);
		featuresResolved = false;
	}

	private SortedSet<ReachablePlugin> findAllReferencedPlugins() throws CoreException {
		ArrayList<BuildTimeFeature> rootFeatures = new ArrayList<BuildTimeFeature>();
		SortedSet<ReachablePlugin> allPlugins = new TreeSet<ReachablePlugin>();
		for (Iterator<String> iter = rootFeaturesForFilter.iterator(); iter.hasNext();) {
			BuildTimeFeature correspondingFeature = findFeature(iter.next(), (String) null, true);
			if (correspondingFeature == null)
				return null;
			rootFeatures.add(correspondingFeature);
		}
		for (Iterator<String> iter = rootPluginsForFiler.iterator(); iter.hasNext();) {
			allPlugins.add(new ReachablePlugin(iter.next(), ReachablePlugin.WIDEST_RANGE));
		}
		int it = 0;
		while (it < rootFeatures.size()) {
			BuildTimeFeature toAnalyse = null;
			try {
				toAnalyse = rootFeatures.get(it++);
			} catch (RuntimeException e) {
				e.printStackTrace();
			}
			FeatureEntry[] includedRefs = toAnalyse.getIncludedFeatureReferences();
			for (int i = 0; i < includedRefs.length; i++) {
				String featureId = includedRefs[i].getId();
				BuildTimeFeature nested = findFeature(featureId, includedRefs[i].getVersion(), false);
				if (nested != null)
					rootFeatures.add(nested);
				else {
					// missing feature, ok if it will be a generated source feature
					Properties props = AbstractScriptGenerator.readProperties(toAnalyse.getRootLocation(), PROPERTIES_FILE, IStatus.OK);
					boolean doSourceFeatureGeneration = props.containsKey(IBuildPropertiesConstants.GENERATION_SOURCE_FEATURE_PREFIX + featureId);
					if (doSourceFeatureGeneration) {
						//generate property may add extra plugins or features
						String[] extraEntries = Utils.getArrayFromString(props.getProperty(IBuildPropertiesConstants.GENERATION_SOURCE_FEATURE_PREFIX + featureId));
						for (int j = 1; j < extraEntries.length; j++) {
							Map<String, Object> items = Utils.parseExtraBundlesString(extraEntries[j], true);
							String id = (String) items.get(Utils.EXTRA_ID);
							Version version = (Version) items.get(Utils.EXTRA_VERSION);
							if (extraEntries[j].startsWith("feature@")) { //$NON-NLS-1$
								FeatureEntry added = new FeatureEntry(id, version.toString(), false);
								FeatureEntry[] expanded = new FeatureEntry[includedRefs.length + 1];
								System.arraycopy(includedRefs, 0, expanded, 0, includedRefs.length);
								expanded[includedRefs.length] = added;
								includedRefs = expanded;
							} else if (extraEntries[j].startsWith("plugin@")) { //$NON-NLS-1$
								VersionRange range = new VersionRange(version, true, version.equals(Version.emptyVersion) ? (Version) null : version, true);
								allPlugins.add(new ReachablePlugin(id, range));
							}
						}
					} else {
						String message = NLS.bind(Messages.exception_missingFeature, featureId);
						throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_FEATURE_MISSING, message, null));
					}
				}
			}
			FeatureEntry[] entries = toAnalyse.getPluginEntries();
			for (int i = 0; i < entries.length; i++) {
				allPlugins.add(new ReachablePlugin(entries[i]));
			}
			FeatureEntry[] imports = toAnalyse.getImports();
			for (int i = 0; i < imports.length; i++) {
				if (!imports[i].isPlugin()) {
					rootFeatures.add(findFeature(imports[i].getId(), Utils.createVersionRange(imports[i]), true));
				} else {
					allPlugins.add(new ReachablePlugin(imports[i]));
				}
			}
		}
		return allPlugins;
	}

	public void setFilter(boolean filter) {
		this.filter = filter;
	}

	public void setRootFeaturesForFilter(List<String> rootFeaturesForFilter) {
		this.rootFeaturesForFilter = rootFeaturesForFilter;
	}

	public void setRootPluginsForFiler(List<String> rootPluginsForFiler) {
		this.rootPluginsForFiler = rootPluginsForFiler;
	}

	public FeatureReference[] getFeatureReferences() {
		return getRawFeatureReferences();

	}

	public FeatureReference[] getRawFeatureReferences() {
		if (featureReferences == null || featureReferences.size() == 0)
			return new FeatureReference[0];
		return featureReferences.toArray(new FeatureReference[featureReferences.size()]);
	}

	public void addPluginEntry(FeatureEntry pluginEntry) {
		// TODO Auto-generated method stub
	}

	public Feature createFeature(URL url) throws CoreException {
		BuildTimeFeature feature = featureURLCache.get(url);
		if (feature != null)
			return feature;

		feature = factory.createFeature(url, this);
		feature.setFeatureContentProvider(getSiteContentProvider());
		featureURLCache.put(url, feature);

		if (featureCache.containsKey(feature.getId())) {
			Set<BuildTimeFeature> set = featureCache.get(feature.getId());
			set.add(feature);
		} else {
			TreeSet<BuildTimeFeature> set = new TreeSet<BuildTimeFeature>(featureComparator);
			set.add(feature);
			featureCache.put(feature.getId(), set);
		}

		return feature;
	}

	public BuildTimeSiteContentProvider getSiteContentProvider() {
		return contentProvider;
	}

	public void setSiteContentProvider(BuildTimeSiteContentProvider siteContentProvider) {
		this.contentProvider = siteContentProvider;
	}

	public void setEESources(String[] eeSources) {
		this.eeSources = eeSources;
	}
}
