/*******************************************************************************
 * 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 Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.core;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.importing.provisional.IBundleImporter;
import org.eclipse.team.core.mapping.IStorageMerger;
import org.eclipse.team.internal.core.FileContentManager;
import org.eclipse.team.internal.core.Messages;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.StorageMergerRegistry;
import org.eclipse.team.internal.core.StringMatcher;
import org.eclipse.team.internal.core.TeamPlugin;
import org.eclipse.team.internal.core.TeamResourceChangeListener;
import org.eclipse.team.internal.core.importing.BundleImporterExtension;

/**
 * The Team class provides a global point of reference for the global ignore set
 * and the text/binary registry.
 *
 * @since 2.0
 */
public final class Team {

	private static class StringMappingWrapper implements IFileTypeInfo {

		private final IStringMapping fMapping;

		public StringMappingWrapper(IStringMapping mapping) {
			fMapping= mapping;
		}

		@Override
		public String getExtension() {
			return fMapping.getString();
		}

		@Override
		public int getType() {
			return fMapping.getType();
		}

	}

	private static final String PREF_TEAM_IGNORES = "ignore_files"; //$NON-NLS-1$
	private static final String PREF_TEAM_SEPARATOR = "\n"; //$NON-NLS-1$
	public static final Status OK_STATUS = new Status(IStatus.OK, TeamPlugin.ID, IStatus.OK, Messages.ok, null);

	// File type constants
	public static final int UNKNOWN = 0;
	public static final int TEXT = 1;
	public static final int BINARY = 2;


	// The ignore list that is read at startup from the persisted file
	protected static SortedMap<String, Boolean> globalIgnore, pluginIgnore;
	private static StringMatcher[] ignoreMatchers;

	private final static FileContentManager fFileContentManager;

	private static List<IBundleImporter> fBundleImporters;

	static {
		fFileContentManager= new FileContentManager();
	}


	/**
	 * Return the type of the given IStorage. First, we check whether a mapping has
	 * been defined for the name of the IStorage. If this is not the case, we check for
	 * a mapping with the extension. If no mapping is defined, UNKNOWN is returned.
	 *
	 * Valid return values are:
	 * Team.TEXT
	 * Team.BINARY
	 * Team.UNKNOWN
	 *
	 * @param storage  the IStorage
	 * @return whether the given IStorage is TEXT, BINARY, or UNKNOWN
	 *
	 * @deprecated Use <code>getFileContentManager().getType(IStorage storage)</code> instead.
	 */
	@Deprecated
	public static int getType(IStorage storage) {
		return fFileContentManager.getType(storage);
	}

	/**
	 * Returns whether the given file or folder with its content should be ignored.
	 *
	 * This method answers true if the file matches one of the global ignore
	 * patterns, or if the file is marked as derived.
	 *
	 * @param resource the file or folder
	 * @return whether the file should be ignored
	 */
	public static boolean isIgnoredHint(IResource resource) {
		if (resource.isDerived()) return true;
		return matchesEnabledIgnore(resource);
	}

	/**
	 * Returns whether the given file should be ignored.
	 * @param file file to check
	 * @return <code>true</code> if this file should be ignored, and <code>false</code> otherwise
	 * @deprecated use isIgnoredHint(IResource) instead
	 */
	@Deprecated
	public static boolean isIgnoredHint(IFile file) {
		if (file.isDerived()) return true;
		return matchesEnabledIgnore(file);
	}

	private static boolean matchesEnabledIgnore(IResource resource) {
		StringMatcher[] matchers = getStringMatchers();
		for (int i = 0; i < matchers.length; i++) {
			String resourceName = resource.getName();
			if(matchers[i].isPathPattern()) {
				resourceName = resource.getFullPath().toString();
			}
			if (matchers[i].match(resourceName)) return true;
		}
		return false;
	}

	/**
	 * Returns whether the given file should be ignored.
	 * @param file file to check
	 * @return <code>true</code> if this file should be ignored, and <code>false</code> otherwise
	 * @deprecated use isIgnoredHint instead
	 */
	@Deprecated
	public static boolean isIgnored(IFile file) {
		return matchesEnabledIgnore(file);
	}


	/**
	 * Return all known file types.
	 *
	 * @return all known file types
	 * @deprecated Use <code>getFileContentManager().getExtensionMappings()</code> instead.
	 */
	@Deprecated
	public static IFileTypeInfo[] getAllTypes() {
		final IStringMapping [] mappings= fFileContentManager.getExtensionMappings();
		final IFileTypeInfo [] infos= new IFileTypeInfo[mappings.length];
		for (int i = 0; i < infos.length; i++) {
			infos[i]= new StringMappingWrapper(mappings[i]);
		}
		return infos;
	}

	/**
	 * Returns the list of global ignores.
	 * @return all ignore infos representing globally ignored patterns
	 */
	public synchronized static IIgnoreInfo[] getAllIgnores() {
		// The ignores are cached and when the preferences change the
		// cache is cleared. This makes it faster to lookup without having
		// to re-parse the preferences.
		initializeIgnores();
		IIgnoreInfo[] result = getIgnoreInfo(globalIgnore);
		return result;
	}

	private static void initializeIgnores() {
		if (globalIgnore == null) {
			globalIgnore = new TreeMap<>();
			pluginIgnore = new TreeMap<>();
			ignoreMatchers = null;
			try {
				readIgnoreState();
			} catch (TeamException e) {
				TeamPlugin.log(IStatus.ERROR, Messages.Team_Error_loading_ignore_state_from_disk_1, e);
			}
			initializePluginIgnores(pluginIgnore, globalIgnore);
		}
	}

	private static IIgnoreInfo[] getIgnoreInfo(Map gIgnore) {
		IIgnoreInfo[] result = new IIgnoreInfo[gIgnore.size()];
		Iterator e = gIgnore.entrySet().iterator();
		int i = 0;
		while (e.hasNext() ) {
			Map.Entry entry = (Entry) e.next();
			final String pattern = (String) entry.getKey();
			final boolean enabled = ((Boolean)entry.getValue()).booleanValue();
			result[i++] = new IIgnoreInfo() {
				private String p = pattern;
				private boolean e1 = enabled;
				@Override
				public String getPattern() {
					return p;
				}
				@Override
				public boolean getEnabled() {
					return e1;
				}
			};
		}
		return result;
	}

	private synchronized static StringMatcher[] getStringMatchers() {
		if (ignoreMatchers==null) {
			IIgnoreInfo[] ignorePatterns = getAllIgnores();
			ArrayList<StringMatcher> matchers = new ArrayList<>(ignorePatterns.length);
			for (int i = 0; i < ignorePatterns.length; i++) {
				if (ignorePatterns[i].getEnabled()) {
					matchers.add(new StringMatcher(ignorePatterns[i].getPattern(), true, false));
				}
			}
			ignoreMatchers = new StringMatcher[matchers.size()];
			ignoreMatchers = matchers.toArray(ignoreMatchers);
		}
		return ignoreMatchers;
	}


	/**
	 * Set the file type for the give extensions. This
	 * will replace the existing file types with this new list.
	 *
	 * Valid types are:
	 * Team.TEXT
	 * Team.BINARY
	 * Team.UNKNOWN
	 *
	 * @param extensions  the file extensions
	 * @param types  the file types
	 *
	 * @deprecated Use <code>getFileContentManager().setExtensionMappings()</code> instead.
	 */
	@Deprecated
	public static void setAllTypes(String[] extensions, int[] types) {
		fFileContentManager.addExtensionMappings(extensions, types);
	}

	/**
	 * Add patterns to the list of global ignores.
	 *
	 * @param patterns Array of patterns to set
	 * @param enabled Array of booleans indicating if given pattern is enabled
	 */
	public static void setAllIgnores(String[] patterns, boolean[] enabled) {
		initializeIgnores();
		globalIgnore = new TreeMap<>();
		ignoreMatchers = null;
		for (int i = 0; i < patterns.length; i++) {
			globalIgnore.put(patterns[i], Boolean.valueOf(enabled[i]));
		}
		// Now set into preferences
		StringBuilder buf = new StringBuilder();
		Iterator e = globalIgnore.entrySet().iterator();
		while (e.hasNext()) {
			Map.Entry entry = (Entry) e.next();
			String pattern = (String) entry.getKey();
			Boolean value = (Boolean) entry.getValue();
			boolean isCustom = (!pluginIgnore.containsKey(pattern)) ||
				!pluginIgnore.get(pattern).equals(value);
			if (isCustom) {
				buf.append(pattern);
				buf.append(PREF_TEAM_SEPARATOR);
				boolean en = value.booleanValue();
				buf.append(en);
				buf.append(PREF_TEAM_SEPARATOR);
			}

		}
		TeamPlugin.getPlugin().getPluginPreferences().setValue(PREF_TEAM_IGNORES, buf.toString());
	}




	/*
	 * IGNORE
	 *
	 * Reads the ignores currently defined by extensions.
	 */
	private static void initializePluginIgnores(SortedMap<String, Boolean> pIgnore, SortedMap<String, Boolean> gIgnore) {
		TeamPlugin plugin = TeamPlugin.getPlugin();
		if (plugin != null) {
			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(TeamPlugin.ID, TeamPlugin.IGNORE_EXTENSION);
			if (extension != null) {
				IExtension[] extensions =  extension.getExtensions();
				for (int i = 0; i < extensions.length; i++) {
					IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
					for (int j = 0; j < configElements.length; j++) {
						String pattern = configElements[j].getAttribute("pattern"); //$NON-NLS-1$
						if (pattern != null) {
							String selected = configElements[j].getAttribute("enabled"); //$NON-NLS-1$
							if (selected == null) {
								// Check for selected because this used to be the field name
								selected = configElements[j].getAttribute("selected"); //$NON-NLS-1$
							}
							boolean enabled = selected != null
									&& selected.equalsIgnoreCase("true"); //$NON-NLS-1$
							if (!pIgnore.containsKey(pattern)) {
								pIgnore.put(pattern, Boolean.valueOf(enabled));
							} else if (!Boolean.valueOf(enabled).equals(
									pIgnore.get(pattern))) {
								if(Policy.DEBUG){
									TeamPlugin
											.log(IStatus.WARNING,
													NLS.bind(
															Messages.Team_Conflict_occured_for_ignored_resources_pattern,
															new Object[] {
																	pattern,
																	collectContributingExtentionsToDisplay(
																			pattern,
																			extensions) }),
													null);
								}
								// if another plug-in already added this pattern
								// change the value only to disabled
								if (!enabled) {
									pIgnore.put(pattern,
											Boolean.FALSE);
								}
							}
						}
					}
				}

				Iterator<String> it = pIgnore.keySet().iterator();
				while (it.hasNext()) {
					String pattern = it.next();
					if (!gIgnore.containsKey(pattern)) {
						gIgnore.put(pattern, pIgnore.get(pattern));
					}
				}
			}
		}
	}

	private static String collectContributingExtentionsToDisplay(
			String patternToFind, IExtension[] extensions) {
		StringBuilder sb = new StringBuilder();
		boolean isFirst = true;
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] configElements = extensions[i]
					.getConfigurationElements();
			for (int j = 0; j < configElements.length; j++) {
				if (patternToFind.equals(configElements[j]
						.getAttribute("pattern"))) { //$NON-NLS-1$
					if (!isFirst) {
						sb.append(", "); //$NON-NLS-1$
					}
					isFirst = false;
					sb.append(extensions[i].getContributor().getName());
				}
			}
		}
		return sb.toString();
	}

	/*
	 * IGNORE
	 *
	 * Reads global ignore preferences and populates globalIgnore
	 */
	private static void readIgnoreState() throws TeamException {
		if (readBackwardCompatibleIgnoreState()) return;
		Preferences pref = TeamPlugin.getPlugin().getPluginPreferences();
		if (!pref.contains(PREF_TEAM_IGNORES)) return;
		pref.addPropertyChangeListener(event -> {
			// when a property is changed, invalidate our cache so that
			// properties will be recalculated.
			if(event.getProperty().equals(PREF_TEAM_IGNORES))
				globalIgnore = null;
		});
		String prefIgnores = pref.getString(PREF_TEAM_IGNORES);
		StringTokenizer tok = new StringTokenizer(prefIgnores, PREF_TEAM_SEPARATOR);
		String pattern, enabled;
		try {
			while (true) {
				pattern = tok.nextToken();
				if (pattern.length()==0) return;
				enabled = tok.nextToken();
				globalIgnore.put(pattern, Boolean.valueOf(enabled));
			}
		} catch (NoSuchElementException e) {
			return;
		}
	}

	/*
	 * For backward compatibility, we still look at if we have .globalIgnores
	 */
	private static boolean readBackwardCompatibleIgnoreState() throws TeamException {
		String GLOBALIGNORE_FILE = ".globalIgnores"; //$NON-NLS-1$
		IPath pluginStateLocation = TeamPlugin.getPlugin().getStateLocation().append(GLOBALIGNORE_FILE);
		File f = pluginStateLocation.toFile();
		if (!f.exists()) return false;
		try {
			DataInputStream dis = new DataInputStream(new FileInputStream(f));
			try {
				int ignoreCount = 0;
				try {
					ignoreCount = dis.readInt();
				} catch (EOFException e) {
					// Ignore the exception, it will occur if there are no ignore
					// patterns stored in the provider state file.
					return false;
				}
				for (int i = 0; i < ignoreCount; i++) {
					String pattern = dis.readUTF();
					boolean enabled = dis.readBoolean();
					globalIgnore.put(pattern, Boolean.valueOf(enabled));
				}
			} finally {
				dis.close();
			}
			f.delete();
		} catch (FileNotFoundException e) {
			// not a fatal error, there just happens not to be any state to read
		} catch (IOException ex) {
			throw new TeamException(new Status(IStatus.ERROR, TeamPlugin.ID, 0, Messages.Team_readError, ex));
		}
		return true;
	}
	/**
	 * Initialize the registry, restoring its state.
	 *
	 * This method is called by the plug-in upon startup, clients should not call this method
	 */
	public static void startup() {
		// Register a delta listener that will tell the provider about a project move and meta-file creation
		ResourcesPlugin.getWorkspace().addResourceChangeListener(new TeamResourceChangeListener(), IResourceChangeEvent.POST_CHANGE);
	}

	/**
	 * Shut down the registry, persisting its state.
	 *
	 * This method is called by the plug-in upon shutdown, clients should not call this method
	 */
	public static void shutdown() {
		TeamPlugin.getPlugin().savePluginPreferences();
	}
	/**
	 * @deprecated
	 * 		Use {@link org.eclipse.team.core.RepositoryProviderType#getProjectSetCapability()}
	 * 		to obtain an instance of {@link ProjectSetCapability} instead.
	 */
	@Deprecated
	public static IProjectSetSerializer getProjectSetSerializer(String id) {
		TeamPlugin plugin = TeamPlugin.getPlugin();
		if (plugin != null) {
			IExtensionPoint extension = RegistryFactory.getRegistry().getExtensionPoint(TeamPlugin.ID, TeamPlugin.PROJECT_SET_EXTENSION);
			if (extension != null) {
				IExtension[] extensions =  extension.getExtensions();
				for (int i = 0; i < extensions.length; i++) {
					IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
					for (int j = 0; j < configElements.length; j++) {
						String extensionId = configElements[j].getAttribute("id"); //$NON-NLS-1$
						if (extensionId != null && extensionId.equals(id)) {
							try {
								return (IProjectSetSerializer)configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
							} catch (CoreException e) {
								TeamPlugin.log(e);
								return null;
							}
						}
					}
				}
			}
		}
		return null;
	}


	/**
	 * Return the default ignore infos
	 * (i.e. those that are specified in
	 * plugin manifests).
	 * @return the default ignore infos.
	 * @since 3.0
	 */
	public static IIgnoreInfo[] getDefaultIgnores() {
		SortedMap<String, Boolean> gIgnore = new TreeMap<>();
		SortedMap<String, Boolean> pIgnore = new TreeMap<>();
		initializePluginIgnores(pIgnore, gIgnore);
		return getIgnoreInfo(gIgnore);
	}

	/**
	 * TODO: change to file content manager
	 * Return the default file type bindings
	 * (i.e. those that are specified in
	 * plugin manifests).
	 * @return the default file type bindings
	 * @since 3.0
	 * @deprecated Use Team.getFileContentManager().getDefaultExtensionMappings() instead.
	 */
	@Deprecated
	public static IFileTypeInfo[] getDefaultTypes() {
		return asFileTypeInfo(getFileContentManager().getDefaultExtensionMappings());
	}

	private static IFileTypeInfo [] asFileTypeInfo(IStringMapping [] mappings) {
		final IFileTypeInfo [] infos= new IFileTypeInfo[mappings.length];
		for (int i = 0; i < infos.length; i++) {
			infos[i]= new StringMappingWrapper(mappings[i]);
		}
		return infos;
	}

	/**
	 * Get the file content manager which implements the API for manipulating the mappings between
	 * file names, file extensions and content types.
	 *
	 * @return an instance of IFileContentManager
	 *
	 * @see IFileContentManager
	 *
	 * @since 3.1
	 */
	public static IFileContentManager getFileContentManager() {
		return fFileContentManager;
	}

	/**
	 * Creates a storage merger for the given content type.
	 * If no storage merger is registered for the given content type <code>null</code> is returned.
	 *
	 * @param type the type for which to find a storage merger
	 * @return a storage merger for the given type, or <code>null</code> if no
	 *   storage merger has been registered
	 *
	 * @since 3.4
	 */
	public static IStorageMerger createMerger(IContentType type) {
		return StorageMergerRegistry.getInstance().createStreamMerger(type);
	}

	/**
	 * Creates a storage merger for the given file extension.
	 * If no storage merger is registered for the file extension <code>null</code> is returned.
	 *
	 * @param extension the extension for which to find a storage merger
	 * @return a stream merger for the given type, or <code>null</code> if no
	 *   storage merger has been registered
	 *
	 * @since 3.4
	 */
	public static IStorageMerger createMerger(String extension) {
		return StorageMergerRegistry.getInstance().createStreamMerger(extension);
	}

	/**
	 * Creates a storage merger for the given content type.
	 * If no storage merger is registered for the given content type <code>null</code> is returned.
	 *
	 * @param type the type for which to find a storage merger
	 * @return a storage merger for the given type, or <code>null</code> if no
	 *   storage merger has been registered
	 * @deprecated Use {@link #createMerger(IContentType)} instead.
	 * @since 3.2
	 */
	@Deprecated
	public IStorageMerger createStorageMerger(IContentType type) {
		return createMerger(type);
	}

	/**
	 * Creates a storage merger for the given file extension.
	 * If no storage merger is registered for the file extension <code>null</code> is returned.
	 *
	 * @param extension the extension for which to find a storage merger
	 * @return a stream merger for the given type, or <code>null</code> if no
	 *   storage merger has been registered
	 * @deprecated Use {@link #createMerger(String)} instead.
	 * @since 3.2
	 */
	@Deprecated
	public IStorageMerger createStorageMerger(String extension) {
		return createMerger(extension);
	}

	/**
	 * Returns the available bundle importers.
	 *
	 * <p>
	 * <strong>EXPERIMENTAL</strong>. This interface has been added as part of a
	 * work in progress. There is no guarantee that this API will work or that
	 * it will remain the same. Please do not use this API without consulting
	 * with the Team team.
	 * </p>
	 *
	 * @return IBundleImporter[] returns the available bundle importers
	 * @since 3.6
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public synchronized static IBundleImporter[] getBundleImporters() {
		if (fBundleImporters == null) {
			fBundleImporters = new ArrayList<>();
			IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(TeamPlugin.EXTENSION_POINT_BUNDLE_IMPORTERS);
			if (point != null) {
				IConfigurationElement[] infos = point.getConfigurationElements();
				for (int i = 0; i < infos.length; i++) {
					fBundleImporters.add(new BundleImporterExtension(infos[i]));
				}
			}
		}
		return fBundleImporters.toArray(new IBundleImporter[fBundleImporters.size()]);
	}
}
