/*******************************************************************************
 * Copyright (c) 2000, 2017 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 - 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<>();
	private final Map<URL, BuildTimeFeature> featureURLCache = new HashMap<>();
	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))) {
				repositoryVersions.load(input);
			} 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<>(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<>(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<>();

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

	private SortedSet<ReachablePlugin> findAllReferencedPlugins() throws CoreException {
		ArrayList<BuildTimeFeature> rootFeatures = new ArrayList<>();
		SortedSet<ReachablePlugin> allPlugins = new TreeSet<>();
		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<>(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;
	}
}
