/*******************************************************************************
 * Copyright (c) 2008, 2015 Freescale Semiconductor 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:
 *     Serge Beauchamp (Freescale Semiconductor) - initial API and implementation
 *     IBM Corporation - ongoing development
 *     James Blackburn (Broadcom Corp.) - ongoing development
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.osgi.util.NLS;

/**
 * The {@link IPathVariableManager} for a single project
 * @see IProject#getPathVariableManager()
 */
public class ProjectPathVariableManager implements IPathVariableManager, IManager {

	private Resource resource;
	private ProjectVariableProviderManager.Descriptor variableProviders[] = null;

	/**
	 * Constructor for the class.
	 */
	public ProjectPathVariableManager(Resource resource) {
		this.resource = resource;
		variableProviders = ProjectVariableProviderManager.getDefault().getDescriptors();
	}

	PathVariableManager getWorkspaceManager() {
		return (PathVariableManager) resource.getWorkspace().getPathVariableManager();
	}

	/**
	 * Throws a runtime exception if the given name is not valid as a path
	 * variable name.
	 */
	private void checkIsValidName(String name) throws CoreException {
		IStatus status = validateName(name);
		if (!status.isOK())
			throw new CoreException(status);
	}

	/**
	 * Throws an exception if the given path is not valid as a path variable
	 * value.
	 */
	private void checkIsValidValue(URI newValue) throws CoreException {
		IStatus status = validateValue(newValue);
		if (!status.isOK())
			throw new CoreException(status);
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#getPathVariableNames()
	 */
	@Override
	public String[] getPathVariableNames() {
		List<String> result = new LinkedList<>();
		HashMap<String, VariableDescription> map;
		try {
			map = ((ProjectDescription) resource.getProject().getDescription()).getVariables();
		} catch (CoreException e) {
			return new String[0];
		}
		for (int i = 0; i < variableProviders.length; i++) {
			String[] variableHints = variableProviders[i].getVariableNames(variableProviders[i].getName(), resource);
			if (variableHints != null && variableHints.length > 0)
				for (int k = 0; k < variableHints.length; k++)
					result.add(variableProviders[i].getVariableNames(variableProviders[i].getName(), resource)[k]);
		}
		if (map != null)
			result.addAll(map.keySet());
		result.addAll(Arrays.asList(getWorkspaceManager().getPathVariableNames()));
		return result.toArray(new String[0]);
	}

	/**
	 * @deprecated use {@link #getURIValue(String)} instead.
	 */
	@Deprecated
	@Override
	public IPath getValue(String varName) {
		URI uri = getURIValue(varName);
		if (uri != null)
			return URIUtil.toPath(uri);
		return null;
	}

	/**
	 * If the variable is not listed in the project description, we fall back on
	 * the workspace variables.
	 *
	 * @see org.eclipse.core.resources.IPathVariableManager#getURIValue(String)
	 */
	@Override
	public URI getURIValue(String varName) {
		String value = internalGetValue(varName);
		if (value != null) {
			if (value.indexOf("..") != -1) { //$NON-NLS-1$
				// if the path is 'reducible', lets resolve it first.
				int index = value.indexOf(IPath.SEPARATOR);
				if (index > 0) { // if its the first character, its an
					// absolute path on unix, so we don't
					// resolve it
					URI resolved = resolveVariable(value);
					if (resolved != null)
						return resolved;
				}
			}
			try {
				return URI.create(value);
			} catch (IllegalArgumentException e) {
				IPath path = Path.fromPortableString(value);
				return URIUtil.toURI(path);
			}
		}
		return getWorkspaceManager().getURIValue(varName);
	}

	public String internalGetValue(String varName) {
		HashMap<String, VariableDescription> map;
		try {
			map = ((ProjectDescription) resource.getProject().getDescription()).getVariables();
		} catch (CoreException e) {
			return null;
		}
		if (map != null && map.containsKey(varName))
			return map.get(varName).getValue();

		String name;
		int index = varName.indexOf('-');
		if (index != -1)
			name = varName.substring(0, index);
		else
			name = varName;
		for (int i = 0; i < variableProviders.length; i++) {
			if (variableProviders[i].getName().equals(name))
				return variableProviders[i].getValue(varName, resource);
		}
		for (int i = 0; i < variableProviders.length; i++) {
			if (name.startsWith(variableProviders[i].getName()))
				return variableProviders[i].getValue(varName, resource);
		}
		return null;
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#isDefined(String)
	 */
	@Override
	public boolean isDefined(String varName) {
		for (int i = 0; i < variableProviders.length; i++) {
			//			if (variableProviders[i].getName().equals(varName))
			//				return true;

			if (varName.startsWith(variableProviders[i].getName()))
				return true;
		}

		try {
			HashMap<String, VariableDescription> map = ((ProjectDescription) resource.getProject().getDescription()).getVariables();
			if (map != null) {
				Iterator<String> it = map.keySet().iterator();
				while (it.hasNext()) {
					String name = it.next();
					if (name.equals(varName))
						return true;
				}
			}
		} catch (CoreException e) {
			return false;
		}
		boolean value = getWorkspaceManager().isDefined(varName);
		if (!value) {
			// this is to handle variables with encoded arguments
			int index = varName.indexOf('-');
			if (index != -1) {
				String newVarName = varName.substring(0, index);
				value = isDefined(newVarName);
			}
		}
		return value;
	}

	/**
	 * @deprecated use {@link #resolveURI(URI)} instead.
	 */
	@Override
	@Deprecated
	public IPath resolvePath(IPath path) {
		if (path == null || path.segmentCount() == 0 || path.isAbsolute() || path.getDevice() != null)
			return path;
		URI value = resolveURI(URIUtil.toURI(path));
		return value == null ? path : URIUtil.toPath(value);
	}

	public URI resolveVariable(String variable) {
		LinkedList<String> variableStack = new LinkedList<>();

		String value = resolveVariable(variable, variableStack);
		if (value != null) {
			try {
				return URI.create(value);
			} catch (IllegalArgumentException e) {
				return URIUtil.toURI(Path.fromPortableString(value));
			}
		}
		return null;
	}

	public String resolveVariable(String value, LinkedList<String> variableStack) {
		if (variableStack == null)
			variableStack = new LinkedList<>();

		String tmp = internalGetValue(value);
		if (tmp == null) {
			URI result = getWorkspaceManager().getURIValue(value);
			if (result != null)
				return result.toASCIIString();
		} else
			value = tmp;

		while (true) {
			String stringValue;
			try {
				URI uri = URI.create(value);
				if (uri != null) {
					IPath path = URIUtil.toPath(uri);
					if (path != null)
						stringValue = path.toPortableString();
					else
						stringValue = value;
				} else
					stringValue = value;
			} catch (IllegalArgumentException e) {
				stringValue = value;
			}
			// we check if the value contains referenced variables with ${VAR}
			int index = stringValue.indexOf("${"); //$NON-NLS-1$
			if (index != -1) {
				int endIndex = PathVariableUtil.getMatchingBrace(stringValue, index);
				String macro = stringValue.substring(index + 2, endIndex);
				String resolvedMacro = ""; //$NON-NLS-1$
				if (!variableStack.contains(macro)) {
					variableStack.add(macro);
					resolvedMacro = resolveVariable(macro, variableStack);
					if (resolvedMacro == null)
						resolvedMacro = ""; //$NON-NLS-1$
				}
				if (stringValue.length() > endIndex)
					stringValue = stringValue.substring(0, index) + resolvedMacro + stringValue.substring(endIndex + 1);
				else
					stringValue = resolvedMacro;
				value = stringValue;
			} else
				break;
		}
		return value;
	}

	@Override
	public URI resolveURI(URI uri) {
		if (uri == null || uri.isAbsolute() || (uri.getSchemeSpecificPart() == null))
			return uri;
		IPath raw = new Path(uri.getSchemeSpecificPart());
		if (raw == null || raw.segmentCount() == 0 || raw.isAbsolute() || raw.getDevice() != null)
			return URIUtil.toURI(raw);
		URI value = resolveVariable(raw.segment(0));
		if (value == null)
			return uri;

		String path = value.getPath();
		if (path != null) {
			IPath p = Path.fromPortableString(path);
			p = p.append(raw.removeFirstSegments(1));
			try {
				value = new URI(value.getScheme(), value.getHost(), p.toPortableString(), value.getFragment());
			} catch (URISyntaxException e) {
				return uri;
			}
			return value;
		}
		return uri;
	}

	/**
	 * @deprecated use {@link #setURIValue(String, URI)} instead.
	 */
	@Deprecated
	@Override
	public void setValue(String varName, IPath newValue) throws CoreException {
		if (newValue == null)
			setURIValue(varName, (URI) null);
		else
			setURIValue(varName, URIUtil.toURI(newValue));
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#setValue(String,
	 *      IPath)
	 */
	@Override
	public void setURIValue(String varName, URI newValue) throws CoreException {
		checkIsValidName(varName);
		checkIsValidValue(newValue);
		// read previous value and set new value atomically in order to generate
		// the right event
		boolean changeWorkspaceValue = false;
		Project project = (Project) resource.getProject();
		int eventType = 0;
		synchronized (this) {
			String value = internalGetValue(varName);
			URI currentValue = null;
			if (value == null)
				currentValue = getWorkspaceManager().getURIValue(varName);
			else {
				try {
					currentValue = URI.create(value);
				} catch (IllegalArgumentException e) {
					currentValue = null;
				}
			}
			boolean variableExists = currentValue != null;
			if (!variableExists && newValue == null)
				return;
			if (variableExists && currentValue.equals(newValue))
				return;

			for (int i = 0; i < variableProviders.length; i++) {
				//				if (variableProviders[i].getName().equals(varName))
				//					return;

				if (varName.startsWith(variableProviders[i].getName()))
					return;
			}

			if (value == null && variableExists)
				changeWorkspaceValue = true;
			else {
				IProgressMonitor monitor = new NullProgressMonitor();
				final ISchedulingRule rule = resource.getProject(); // project.workspace.getRuleFactory().modifyRule(project);
				try {
					project.workspace.prepareOperation(rule, monitor);
					project.workspace.beginOperation(true);
					// save the location in the project description
					ProjectDescription description = project.internalGetDescription();
					if (newValue == null) {
						description.setVariableDescription(varName, null);
						eventType = IPathVariableChangeEvent.VARIABLE_DELETED;
					} else {
						description.setVariableDescription(varName, new VariableDescription(varName, newValue.toASCIIString()));
						eventType = variableExists ? IPathVariableChangeEvent.VARIABLE_CHANGED : IPathVariableChangeEvent.VARIABLE_CREATED;
					}
					project.writeDescription(IResource.NONE);
				} finally {
					project.workspace.endOperation(rule, true);
				}
			}
		}
		if (changeWorkspaceValue)
			getWorkspaceManager().setURIValue(varName, newValue);
		else {
			// notify listeners from outside the synchronized block to avoid deadlocks
			getWorkspaceManager().fireVariableChangeEvent(project, varName, newValue != null ? URIUtil.toPath(newValue) : null, eventType);
		}
	}

	/**
	 * @see org.eclipse.core.internal.resources.IManager#shutdown(IProgressMonitor)
	 */
	@Override
	public void shutdown(IProgressMonitor monitor) {
		// nothing to do here
	}

	/**
	 * @see org.eclipse.core.internal.resources.IManager#startup(IProgressMonitor)
	 */
	@Override
	public void startup(IProgressMonitor monitor) {
		// nothing to do here
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#validateName(String)
	 */
	@Override
	public IStatus validateName(String name) {
		String message = null;
		if (name.length() == 0) {
			message = Messages.pathvar_length;
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}

		char first = name.charAt(0);
		if (!Character.isLetter(first) && first != '_') {
			message = NLS.bind(Messages.pathvar_beginLetter, String.valueOf(first));
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}

		for (int i = 1; i < name.length(); i++) {
			char following = name.charAt(i);
			if (Character.isWhitespace(following))
				return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, Messages.pathvar_whitespace);
			if (!Character.isLetter(following) && !Character.isDigit(following) && following != '_') {
				message = NLS.bind(Messages.pathvar_invalidChar, String.valueOf(following));
				return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
			}
		}
		// check

		return Status.OK_STATUS;
	}

	/**
	 * @see IPathVariableManager#validateValue(IPath)
	 */
	@Override
	public IStatus validateValue(IPath value) {
		// accept any format
		return Status.OK_STATUS;
	}

	/**
	 * @see IPathVariableManager#validateValue(URI)
	 */
	@Override
	public IStatus validateValue(URI value) {
		// accept any format
		return Status.OK_STATUS;
	}

	/**
	 * @throws CoreException
	 * @see IPathVariableManager#convertToRelative(URI, boolean, String)
	 */
	@Override
	public URI convertToRelative(URI path, boolean force, String variableHint) throws CoreException {
		return PathVariableUtil.convertToRelative(this, path, resource, force, variableHint);
	}

	/**
	 * @see IPathVariableManager#convertToUserEditableFormat(String, boolean)
	 */
	@Override
	public String convertToUserEditableFormat(String value, boolean locationFormat) {
		return PathVariableUtil.convertToUserEditableFormatInternal(value, locationFormat);
	}

	@Override
	public String convertFromUserEditableFormat(String userFormat, boolean locationFormat) {
		return PathVariableUtil.convertFromUserEditableFormatInternal(this, userFormat, locationFormat);
	}

	@Override
	public void addChangeListener(IPathVariableChangeListener listener) {
		getWorkspaceManager().addChangeListener(listener, resource.getProject());
	}

	@Override
	public void removeChangeListener(IPathVariableChangeListener listener) {
		getWorkspaceManager().removeChangeListener(listener, resource.getProject());
	}

	@Override
	public URI getVariableRelativePathLocation(URI location) {
		try {
			URI result = convertToRelative(location, false, null);
			if (!result.equals(location))
				return result;
		} catch (CoreException e) {
			// handled by returning null
		}
		return null;
	}

	/*
	 * Return the resource of this manager.
	 */
	public IResource getResource() {
		return resource;
	}

	@Override
	public boolean isUserDefined(String name) {
		return ProjectVariableProviderManager.getDefault().findDescriptor(name) == null;
	}
}
