/*******************************************************************************
 *  Copyright (c) 2005, 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
 *******************************************************************************/
package org.eclipse.jdt.internal.launching.environments;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.launching.LaunchingPlugin;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallChangedListener;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.LibraryLocation;
import org.eclipse.jdt.launching.PropertyChangeEvent;
import org.eclipse.jdt.launching.environments.IAccessRuleParticipant;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;

/**
 * A contributed execution environment.
 *
 * @since 3.2
 */
class ExecutionEnvironment implements IExecutionEnvironment {

	/**
	 * Add a VM changed listener to clear cached values when a VM changes or is removed
	 */
	private IVMInstallChangedListener fListener = new IVMInstallChangedListener() {

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#defaultVMInstallChanged(org.eclipse.jdt.launching.IVMInstall, org.eclipse.jdt.launching.IVMInstall)
		 */
		@Override
		public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) {}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmAdded(org.eclipse.jdt.launching.IVMInstall)
		 */
		@Override
		public void vmAdded(IVMInstall newVm) {}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmChanged(org.eclipse.jdt.launching.PropertyChangeEvent)
		 */
		@Override
		public void vmChanged(PropertyChangeEvent event) {
			if (event.getSource() != null) {
				fParticipantMap.remove(event.getSource());
				fRuleCache.remove(event.getSource());
			}
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmRemoved(org.eclipse.jdt.launching.IVMInstall)
		 */
		@Override
		public void vmRemoved(IVMInstall removedVm) {
			fParticipantMap.remove(removedVm);
			fRuleCache.remove(removedVm);
		}
	};


	/**
	 * The backing <code>IConfigurationElement</code>
	 */
	private IConfigurationElement fElement;

	/**
	 * Environment specific rule participant or <code>null</code> if none.
	 */
	private IAccessRuleParticipant fRuleParticipant;

	/**
	 * OSGi profile properties or <code>null</code> if none.
	 */
	private Properties fProfileProperties;

	/**
	 * Whether profile properties have been initialized
	 */
	private boolean fPropertiesInitialized;

	/**
	 * Set of compatible vm's - just the strictly compatible ones
	 */
	private Set<IVMInstall> fStrictlyCompatible = new HashSet<>();

	/**
	 * All compatible vm's
	 */
	private List<IVMInstall> fCompatibleVMs = new ArrayList<>();

	/**
	 * default VM install or <code>null</code> if none
	 */
	private IVMInstall fDefault = null;

	/**
	 * Cache of access rule participants to consider for this environment.
	 */
	private IAccessRuleParticipant[] fParticipants = null;

	/**
	 * Map of {IVMInstall -> Map of {participant -> IAccessRule[][]}}.
	 * Caches access rules returned by each participant for a given VM.
	 * @since 3.3
	 */
	private Map<IVMInstall, Map<IAccessRuleParticipant, IAccessRule[][]>> fParticipantMap = new HashMap<>();

	/**
	 * Cache of VM -> IAccessRule[][] based on the current state of the participant
	 * map. These are the union of the latest rules generated by the participants
	 * for a specific VM.
	 * @since 3.3
	 */
	private Map<IVMInstall, IAccessRule[][]> fRuleCache = new HashMap<>();

	/**
	 * Wild card pattern matching all files
	 */
	private static final IPath ALL_PATTERN = new Path("**/*"); //$NON-NLS-1$

	/**
	 * Prefix of compiler settings in properties file
	 */
	private static final String COMPILER_SETTING_PREFIX = JavaCore.PLUGIN_ID + ".compiler"; //$NON-NLS-1$

	/**
	 * Constructor
	 * @param element the backing {@link IConfigurationElement}
	 */
	ExecutionEnvironment(IConfigurationElement element) {
		fElement = element;
		fPropertiesInitialized = false;
		String attribute = fElement.getAttribute(EnvironmentsManager.RULE_PARTICIPANT_ELEMENT);
		if (attribute != null) {
			fRuleParticipant = new AccessRuleParticipant(fElement);
		}
		JavaRuntime.addVMInstallChangedListener(fListener);
	}

	/**
	 * Initializes the <code>EnvironmentsManager</code>
	 */
	private void init() {
		EnvironmentsManager.getDefault().initializeCompatibilities();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getId()
	 */
	@Override
	public String getId() {
		return fElement.getAttribute("id"); //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getDescription()
	 */
	@Override
	public String getDescription() {
		return fElement.getAttribute("description"); //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getCompatibleVMs()
	 */
	@Override
	public IVMInstall[] getCompatibleVMs() {
		init();
		return fCompatibleVMs.toArray(new IVMInstall[fCompatibleVMs.size()]);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#isStrictlyCompatible(org.eclipse.jdt.launching.IVMInstall)
	 */
	@Override
	public boolean isStrictlyCompatible(IVMInstall vm) {
		init();
		return fStrictlyCompatible.contains(vm);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getDefaultVM()
	 */
	@Override
	public IVMInstall getDefaultVM() {
		init();
		return fDefault;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#setDefaultVM(org.eclipse.jdt.launching.IVMInstall)
	 */
	@Override
	public void setDefaultVM(IVMInstall vm) {
		init();
		if (vm != null && !fCompatibleVMs.contains(vm)) {
			throw new IllegalArgumentException(NLS.bind(EnvironmentMessages.EnvironmentsManager_0, new String[]{getId()}));
		}
		if (vm != null && vm.equals(fDefault)) {
			return;
		}
		fDefault = vm;
		EnvironmentsManager.getDefault().updateDefaultVMs();
		// update classpath containers
		rebindClasspathContainers();
	}

	/**
	 * Updates Java projects referencing this environment, if any.
	 */
	private void rebindClasspathContainers() {
		IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
		if (model != null) {
			try {
				List<IJavaProject> updates = new ArrayList<>();
				IJavaProject[] javaProjects = model.getJavaProjects();
				IPath path = JavaRuntime.newJREContainerPath(this);
				for (int i = 0; i < javaProjects.length; i++) {
					IJavaProject project = javaProjects[i];
					IClasspathEntry[] rawClasspath = project.getRawClasspath();
					for (int j = 0; j < rawClasspath.length; j++) {
						IClasspathEntry entry = rawClasspath[j];
						if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
							if (entry.getPath().equals(path)) {
								updates.add(project);
							}
						}
					}
				}
				if (!updates.isEmpty()) {
					JavaCore.setClasspathContainer(path,
							updates.toArray(new IJavaProject[updates.size()]),
							new IClasspathContainer[updates.size()],
							new NullProgressMonitor());
				}
			} catch (JavaModelException e) {
				LaunchingPlugin.log(e);
			}
		}
	}

	/**
	 * Adds the specified VM to the listing of compatible VMs, also
	 * adds the VM to the listing of strictly compatible ones based on
	 * the strictlyCompatible flag
	 * @param vm the VM to add to the environment
	 * @param strictlyCompatible if it is strictly compatible
	 */
	void add(IVMInstall vm, boolean strictlyCompatible) {
		if (fCompatibleVMs.contains(vm)) {
			return;
		}
		fCompatibleVMs.add(vm);
		if (strictlyCompatible) {
			fStrictlyCompatible.add(vm);
		}
	}

	/**
	 * Removes the specified VM from the listings of VMs
	 * @param vm the VM to remove
	 */
	void remove(IVMInstall vm) {
		fCompatibleVMs.remove(vm);
		fStrictlyCompatible.remove(vm);
	}

	/**
	 * Sets the default VM to be the one specified
	 * @param vm the VM to set as the default
	 */
	void initDefaultVM(IVMInstall vm) {
		fDefault = vm;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getAccessRules(org.eclipse.jdt.launching.IVMInstall, org.eclipse.jdt.launching.LibraryLocation[], org.eclipse.jdt.core.IJavaProject)
	 */
	@Override
	public IAccessRule[][] getAccessRules(IVMInstall vm, LibraryLocation[] libraries, IJavaProject project) {
		IAccessRuleParticipant[] participants = getParticipants();
		Map<IAccessRuleParticipant, IAccessRule[][]> rulesByParticipant = collectRulesByParticipant(participants, vm, libraries, project);
		synchronized (this) {
			Map<IAccessRuleParticipant, IAccessRule[][]> cachedRules = fParticipantMap.get(vm);
			if (cachedRules == null || !cachedRules.equals(rulesByParticipant)) {
				ArrayList<List<IAccessRule>> libLists = new ArrayList<>(); // array of lists of access rules
				for (int i = 0; i < libraries.length; i++) {
					libLists.add(new ArrayList<IAccessRule>());
				}
				for (int i = 0; i < participants.length; i++) {
					IAccessRuleParticipant participant = participants[i];
					addRules(rulesByParticipant.get(participant), libLists);
				}
				IAccessRule[][] allRules = new IAccessRule[libraries.length][];
				for (int i = 0; i < libLists.size(); i++) {
					List<IAccessRule> l = libLists.get(i);
					allRules[i] = l.toArray(new IAccessRule[l.size()]);
				}
				fParticipantMap.put(vm, rulesByParticipant);
				fRuleCache.put(vm, allRules);
				return allRules;
			}
			return fRuleCache.get(vm);
		}
	}

	/**
	 * Returns all access rule participants to consider for this environment.
	 * Includes any participant contributed with this environment and all other
	 * stand alone participants.
	 *
	 * @return access rule participants to consider for this environment
	 */
	private synchronized IAccessRuleParticipant[] getParticipants() {
		if (fParticipants == null) {
			// check participants first
			IAccessRuleParticipant[] participants = EnvironmentsManager.getDefault().getAccessRuleParticipants();
			if (fRuleParticipant != null) {
				// ensure environment specific provider is last and not duplicated
				LinkedHashSet<IAccessRuleParticipant> set = new LinkedHashSet<>();
				for (int i = 0; i < participants.length; i++) {
					set.add(participants[i]);
				}
				// remove, add to make last
				set.remove(fRuleParticipant);
				set.add(fRuleParticipant);
				participants = set.toArray(new IAccessRuleParticipant[set.size()]);
			}
			fParticipants = participants;
		}
		return fParticipants;
	}

	/**
	 * Returns a map of participant to the access rules for that participant for the given
	 * VM, libraries, and project.
	 *
	 * @param participants access rule participants
	 * @param vm the VM
	 * @param libraries the {@link LibraryLocation}s
	 * @param project the {@link IJavaProject} context
	 * @return the mapping of {@link IAccessRuleParticipant} to {@link IAccessRule}s
	 */
	private Map<IAccessRuleParticipant, IAccessRule[][]> collectRulesByParticipant(IAccessRuleParticipant[] participants, IVMInstall vm, LibraryLocation[] libraries, IJavaProject project) {
		Map<IAccessRuleParticipant, IAccessRule[][]> map = new HashMap<>();
		for (int i = 0; i < participants.length; i++) {
			// TODO: use safe runnable
			map.put(participants[i], participants[i].getAccessRules(this, vm, libraries, project));
		}
		return map;
	}

	/**
	 * Adds the access rules to each list in the given collection. If the last rule in a
	 * given collection is the wild card pattern then no more rules are added to that collection.
	 *
	 * @param accessRules the list of {@link IAccessRule}s
	 * @param collect the array of lists to collect the {@link IAccessRule}s in
	 */
	private void addRules(IAccessRule[][] accessRules, ArrayList<List<IAccessRule>> collect) {
		for (int i = 0; i < accessRules.length; i++) {
			IAccessRule[] libRules = accessRules[i];
			List<IAccessRule> list = collect.get(i);
			// if the last rule is a **/* pattern, don't add any more rules, as they will have no effect
			if (!list.isEmpty()) {
				IAccessRule lastRule = list.get(list.size() - 1);
				if(lastRule.getPattern().equals(ALL_PATTERN)) {
					continue;
				}
			}
			for (int j = 0; j < libRules.length; j++) {
				list.add(libRules[j]);
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getProfileProperties()
	 */
	@Override
	public Properties getProfileProperties() {
		if (!fPropertiesInitialized) {
			fPropertiesInitialized = true;
			String path = fElement.getAttribute("profileProperties"); //$NON-NLS-1$
			Bundle bundle = null;
			if (path == null) {
				// attempt default profiles known to OSGi
				bundle = Platform.getBundle("org.eclipse.osgi"); //$NON-NLS-1$
				path = getId().replace('/', '_') + ".profile"; //$NON-NLS-1$
			} else {
				// read provided file
				bundle = Platform.getBundle(fElement.getContributor().getName());
			}
			if (bundle != null && path != null) {
				fProfileProperties = getJavaProfileProperties(bundle, path);
			}
		}
		return fProfileProperties;
	}

	/**
	 * Returns properties file contained in the specified bundle at the given
	 * bundle relative path, or <code>null</code> if none.
	 *
	 * @param bundle bundle to locate file in
	 * @param path bundle relative path to properties file
	 * @return properties or <code>null</code> if none
	 */
	private Properties getJavaProfileProperties(Bundle bundle, String path) {
		Properties profile = new Properties();
		URL profileURL = bundle.getEntry(path);
		if (profileURL != null) {
			try (InputStream is = profileURL.openStream()) {
				profileURL = FileLocator.resolve(profileURL);
				if (is != null) {
					profile.load(is);
					fixJavaSE9ComplianceSourceTargetLevels(profile);
				}
			} catch (IOException e) {
				return null;
			}
		} else {
			if (getCompliance() == null) {
				return null;
			}
			profile.setProperty(JavaCore.COMPILER_COMPLIANCE, getCompliance());
			profile.setProperty(JavaCore.COMPILER_SOURCE, getCompliance());
			profile.setProperty(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, getCompliance());
			profile.setProperty("org.eclipse.jdt.core.compiler.problem.assertIdentifier", "error"); //$NON-NLS-1$ //$NON-NLS-2$
			profile.setProperty("org.eclipse.jdt.core.compiler.problem.enumIdentifier", "error"); //$NON-NLS-1$ //$NON-NLS-2$
			profile.setProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, calculateVMExecutionEnvs(new Version(getCompliance())));
			profile.setProperty(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);

		}
		return profile;
	}

	private static final String JAVASE = "JavaSE"; //$NON-NLS-1$

	private String calculateVMExecutionEnvs(Version javaVersion) {
		StringBuilder result = new StringBuilder("OSGi/Minimum-1.0, OSGi/Minimum-1.1, OSGi/Minimum-1.2, JavaSE/compact1-1.8, JavaSE/compact2-1.8, JavaSE/compact3-1.8, JRE-1.1, J2SE-1.2, J2SE-1.3, J2SE-1.4, J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8"); //$NON-NLS-1$
		Version v = new Version(9, 0, 0);
		while (v.compareTo(javaVersion) <= 0) {
			result.append(',').append(' ').append(JAVASE).append('-').append(v.getMajor());
			if (v.getMinor() > 0) {
				result.append('.').append(v.getMinor());
			}
			if (v.getMajor() == javaVersion.getMajor()) {
				v = new Version(v.getMajor(), v.getMinor() + 1, 0);
			} else {
				v = new Version(v.getMajor() + 1, 0, 0);
			}
		}
		return result.toString();
	}


	/**
	 * Bug 470616: [1.9] JavaSE-9 Execution Environment should set proper compiler compliance/source/target levels
	 * <p>
	 * This is a workaround for Bug 495497: [9] JavaSE-9.profile Execution Environment should set compiler levels to 9
	 */
	private void fixJavaSE9ComplianceSourceTargetLevels(Properties profile) {
		if (ExecutionEnvironmentAnalyzer.JavaSE_9.equals(getId())) {
			profile.setProperty(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_9);
			profile.setProperty(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_9);
			profile.setProperty(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_9);
			profile.setProperty(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getSubEnvironments()
	 */
	@Override
	public IExecutionEnvironment[] getSubEnvironments() {
		Properties properties = getProfileProperties();
		Set<IExecutionEnvironment> subenv = new LinkedHashSet<>();
		if (properties != null) {
			@SuppressWarnings("deprecation")
			String subsets = properties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
			if (subsets != null) {
				String[] ids = subsets.split(","); //$NON-NLS-1$
				for (int i = 0; i < ids.length; i++) {
					IExecutionEnvironment sub = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(ids[i].trim());
					if (sub != null && !sub.getId().equals(getId())) {
						subenv.add(sub);
					}
				}
			}
		}
		return subenv.toArray(new IExecutionEnvironment[subenv.size()]);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getComplianceOptions()
	 */
	@Override
	public Map<String, String> getComplianceOptions() {
		Properties properties = getProfileProperties();
		if (properties != null) {
			Map<String, String> map = new HashMap<>();
			Iterator<?> iterator = properties.keySet().iterator();
			while (iterator.hasNext()) {
				String key = (String) iterator.next();
				if (key.startsWith(COMPILER_SETTING_PREFIX)) {
					map.put(key, properties.getProperty(key));
				}
			}
			if (!map.isEmpty()) {
				return map;
			}
		}
		return null;
	}

	private String getCompliance() {
		return fElement.getAttribute("compliance"); //$NON-NLS-1$
	}
}
