/*******************************************************************************
 * Copyright (c) 2000, 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.debug.internal.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IExpressionListener;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.IExpressionsListener;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IWatchExpression;
import org.eclipse.debug.core.model.IWatchExpressionDelegate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ibm.icu.text.MessageFormat;

/**
 * The expression manager manages all registered expressions
 * for the debug plug-in. It is instantiated by the debug plug-in
 * at startup.
 *
 * @see IExpressionManager
 */
public class ExpressionManager extends PlatformObject implements IExpressionManager {

	/**
	 * Ordered collection of registered expressions.
	 */
	private Vector<IExpression> fExpressions = null;

	/**
	 * List of expression listeners
	 */
	private ListenerList<IExpressionListener> fListeners = null;

	/**
	 * List of expressions listeners (plural)
	 */
	private ListenerList<IExpressionsListener> fExpressionsListeners = null;

	/**
	 * Mapping of debug model identifiers (String) to
	 * expression delegate extensions (IConfigurationElement)
	 */
	private Map<String, IConfigurationElement> fWatchExpressionDelegates = new HashMap<>();

	// Constants for add/remove/change/insert/move notification
	private static final int ADDED = 1;
	private static final int CHANGED = 2;
	private static final int REMOVED = 3;
	private static final int INSERTED = 4;
	private static final int MOVED = 5;

	// Preference for persisted watch expressions
	private static final String PREF_WATCH_EXPRESSIONS= "prefWatchExpressions"; //$NON-NLS-1$
	// Persisted watch expression XML tags
	private static final String WATCH_EXPRESSIONS_TAG= "watchExpressions"; //$NON-NLS-1$
	private static final String EXPRESSION_TAG= "expression"; //$NON-NLS-1$
	private static final String TEXT_TAG= "text"; //$NON-NLS-1$
	private static final String ENABLED_TAG= "enabled"; //$NON-NLS-1$
	// XML values
	private static final String TRUE_VALUE= "true"; //$NON-NLS-1$
	private static final String FALSE_VALUE= "false"; //$NON-NLS-1$

	public ExpressionManager() {
		loadPersistedExpressions();
		loadWatchExpressionDelegates();
	}

	/**
	 * Loads the mapping of debug models to watch expression delegates
	 * from the org.eclipse.debug.core.watchExpressionDelegates
	 * extension point.
	 */
	private void loadWatchExpressionDelegates() {
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), "watchExpressionDelegates"); //$NON-NLS-1$
		for (IConfigurationElement element : extensionPoint.getConfigurationElements()) {
			if (element.getName().equals("watchExpressionDelegate")) { //$NON-NLS-1$
				String debugModel = element.getAttribute("debugModel"); //$NON-NLS-1$
				if (debugModel == null || debugModel.length() == 0) {
					continue;
				}
				fWatchExpressionDelegates.put(debugModel, element);
			}
		}
	}

	@Override
	public IWatchExpressionDelegate newWatchExpressionDelegate(String debugModel) {
		try {
			IConfigurationElement element= fWatchExpressionDelegates.get(debugModel);
			if (element != null) {
				return (IWatchExpressionDelegate) element.createExecutableExtension(IConfigurationElementConstants.DELEGATE_CLASS);
			}
			return null;
		} catch (CoreException e) {
			DebugPlugin.log(e);
			return null;
		}
	}

	@Override
	public boolean hasWatchExpressionDelegate(String id) {
		IConfigurationElement element= fWatchExpressionDelegates.get(id);
		return element != null;
	}

	/**
	 * Loads any persisted watch expressions from the preferences.
	 * NOTE: It's important that no setter methods are called on
	 * 		the watchpoints which will fire change events as this
	 * 		will cause an infinite loop (see Bug 27281).
	 */
	private void loadPersistedExpressions() {
		String expressionsString = Platform.getPreferencesService().getString(DebugPlugin.getUniqueIdentifier(), PREF_WATCH_EXPRESSIONS, IInternalDebugCoreConstants.EMPTY_STRING, null);
		if (expressionsString.length() == 0) {
			return;
		}
		Element root;
		try {
			root = DebugPlugin.parseDocument(expressionsString);
		} catch (CoreException e) {
			DebugPlugin.logMessage("An exception occurred while loading watch expressions.", e); //$NON-NLS-1$
			return;
		}
		if (!root.getNodeName().equals(WATCH_EXPRESSIONS_TAG)) {
			DebugPlugin.logMessage("Invalid format encountered while loading watch expressions.", null); //$NON-NLS-1$
			return;
		}
		NodeList list= root.getChildNodes();
		for (int i= 0, numItems= list.getLength(); i < numItems; i++) {
			Node node= list.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element element= (Element) node;
				if (!element.getNodeName().equals(EXPRESSION_TAG)) {
					DebugPlugin.logMessage(MessageFormat.format("Invalid XML element encountered while loading watch expressions: {0}", new Object[] { node.getNodeName() }), null); //$NON-NLS-1$
					continue;
				}
				String expressionText= element.getAttribute(TEXT_TAG);
				if (expressionText.length() > 0) {
					boolean enabled= TRUE_VALUE.equals(element.getAttribute(ENABLED_TAG));
					IWatchExpression expression= newWatchExpression(expressionText, enabled);
					if (fExpressions == null) {
						fExpressions = new Vector<>(list.getLength());
					}
					fExpressions.add(expression);
				} else {
					DebugPlugin.logMessage("Invalid expression entry encountered while loading watch expressions. Expression text is empty.", null); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Creates a new watch expression with the given expression
	 * and the given enablement;
	 *
	 * @param expressionText the text of the expression to be evaluated
	 * @param enabled whether or not the new expression should be enabled
	 * @return the new watch expression
	 */
	private IWatchExpression newWatchExpression(String expressionText, boolean enabled) {
		return new WatchExpression(expressionText, enabled);
	}

	@Override
	public IWatchExpression newWatchExpression(String expressionText) {
		return new WatchExpression(expressionText);
	}

	/**
	 * Persists this manager's watch expressions as XML in the
	 * preference store.
	 */
	public void storeWatchExpressions() {
		String expressionString = IInternalDebugCoreConstants.EMPTY_STRING;
		try {
			expressionString= getWatchExpressionsAsXML();
		} catch (IOException e) {
			DebugPlugin.log(e);
		} catch (ParserConfigurationException e) {
			DebugPlugin.log(e);
		} catch (TransformerException e) {
			DebugPlugin.log(e);
		}
		Preferences.setString(DebugPlugin.getUniqueIdentifier(), PREF_WATCH_EXPRESSIONS, expressionString, null);
	}

	/**
	 * Returns this manager's watch expressions as XML.
	 * @return this manager's watch expressions as XML
	 * @throws IOException if an exception occurs while creating
	 * 		the XML document.
	 * @throws ParserConfigurationException if an exception occurs while creating
	 * 		the XML document.
	 * @throws TransformerException if an exception occurs while creating
	 * 		the XML document.
	 */
	private String getWatchExpressionsAsXML() throws IOException, ParserConfigurationException, TransformerException {
		IExpression[] expressions= getExpressions();
		Document document= LaunchManager.getDocument();
		Element rootElement= document.createElement(WATCH_EXPRESSIONS_TAG);
		document.appendChild(rootElement);
		for (IExpression expression : expressions) {
			if (expression instanceof IWatchExpression) {
				Element element= document.createElement(EXPRESSION_TAG);
				element.setAttribute(TEXT_TAG, expression.getExpressionText());
				element.setAttribute(ENABLED_TAG, ((IWatchExpression) expression).isEnabled() ? TRUE_VALUE : FALSE_VALUE);
				rootElement.appendChild(element);
			}
		}
		return LaunchManager.serializeDocument(document);
	}

	@Override
	public void addExpression(IExpression expression) {
		addExpressions(new IExpression[]{expression});
	}

	@Override
	public void addExpressions(IExpression[] expressions) {
		List<IExpression> added = doAdd(expressions);
		if (!added.isEmpty()) {
			fireUpdate(added.toArray(new IExpression[added.size()]), ADDED);
		}
	}

	/**
	 * Adds the given expressions to the list of managed expressions, and returns a list
	 * of expressions that were actually added. Expressions that already exist in the
	 * managed list are not added.
	 *
	 * @param expressions expressions to add
	 * @return list of expressions that were actually added.
	 */
	private List<IExpression> doAdd(IExpression[] expressions) {
		List<IExpression> added = new ArrayList<>(expressions.length);
		synchronized (this) {
			if (fExpressions == null) {
				fExpressions = new Vector<>(expressions.length);
			}
			for (IExpression expression : expressions) {
				if (fExpressions.indexOf(expression) == -1) {
					added.add(expression);
					fExpressions.add(expression);
				}
			}
		}
		return added;
	}

	@Override
	public synchronized IExpression[] getExpressions() {
		if (fExpressions == null) {
			return new IExpression[0];
		}
		IExpression[] temp= new IExpression[fExpressions.size()];
		fExpressions.copyInto(temp);
		return temp;
	}

	@Override
	public synchronized IExpression[] getExpressions(String modelIdentifier) {
		if (fExpressions == null) {
			return new IExpression[0];
		}
		ArrayList<IExpression> temp = new ArrayList<>(fExpressions.size());
		for (IExpression expression : fExpressions) {
			String id = expression.getModelIdentifier();
			if (id != null && id.equals(modelIdentifier)) {
				temp.add(expression);
			}
		}
		return temp.toArray(new IExpression[temp.size()]);
	}

	/**
	 * Adds the given expressions to the collection of registered expressions
	 * in the workspace and notifies all registered listeners. The expressions
	 * are inserted in the same order as the passed array at the index of the
	 * specified expressions (before or after it depending on the boolean argument).
	 * If no valid insertion location could be found, the expressions are added
	 * to the end of the collection. Has no effect on expressions already registered.
	 *
	 * @param expressions expressions to insert into the collection
	 * @param insertionLocation the expression at the location where expressions will be inserted
	 * @param insertBefore whether to insert the expressions before or after the given insertion location
	 * @since 3.4
	 */
	public void insertExpressions(IExpression[] expressions, IExpression insertionLocation, boolean insertBefore){
		List<IExpression> added = null;
		List<IExpression> inserted = null;
		int insertionIndex = -1;
		synchronized (this) {
			if (fExpressions == null || ((insertionIndex = fExpressions.indexOf(insertionLocation)) < 0)) {
				added = doAdd(expressions);
			} else {
				if (!insertBefore){
					insertionIndex++;
				}
				inserted = new ArrayList<>(expressions.length);
				for (IExpression expression : expressions) {
					if (fExpressions.indexOf(expression) == -1) {
						//Insert in the same order as the array is passed
						fExpressions.add(insertionIndex+inserted.size(), expression);
						inserted.add(expression);
					}
				}
			}
		}
		if (added != null) {
			if (!added.isEmpty()) {
				fireUpdate(added.toArray(new IExpression[added.size()]), ADDED);
			}
			return;
		}
		if (inserted != null) {
			if (!inserted.isEmpty()) {
				fireUpdate(inserted.toArray(new IExpression[inserted.size()]), INSERTED, insertionIndex);
			}
		}
	}

	/**
	 * Moves the given expressions from their location in the collection
	 * of registered expressions in the workspace to the specified insertion
	 * location.  Notifies all registered listeners.  This method has no effect
	 * if an expression does not exist in the collection or if no valid insertion
	 * location could be determined.
	 *
	 * @param expressions expressions to move
	 * @param insertionLocation the expression at the location to insert the moved expressions
	 * @param insertBefore whether to insert the moved expressions before or after the given insertion location
	 * @since 3.4
	 */
	public void moveExpressions(IExpression[] expressions, IExpression insertionLocation, boolean insertBefore){
		List<IExpression> movedExpressions = new ArrayList<>(expressions.length);
		int insertionIndex = -1;
		IExpression[] movedExpressionsArray = null;
		synchronized (this) {
			if (fExpressions == null){
				return;
			}
			insertionIndex = fExpressions.indexOf(insertionLocation);
			if (insertionIndex < 0){
				return;
			}
			if (!insertBefore){
				insertionIndex++;
			}

			for (IExpression expression : expressions) {
				int removeIndex = fExpressions.indexOf(expression);
				if (removeIndex >= 0){
					movedExpressions.add(expression);
					if (removeIndex < insertionIndex){
						insertionIndex--;
					}
					fExpressions.remove(removeIndex);
				}
			}
			movedExpressionsArray = movedExpressions.toArray(new IExpression[movedExpressions.size()]);
			for (int i = 0; i < movedExpressionsArray.length; i++) {
				// Insert the expressions in the same order as the passed array
				fExpressions.add(insertionIndex+i,movedExpressionsArray[i]);
			}
		}

		if (!movedExpressions.isEmpty()) {
			fireUpdate(movedExpressionsArray, MOVED, insertionIndex);
		}
	}

	@Override
	public void removeExpression(IExpression expression) {
		removeExpressions(new IExpression[] {expression});
	}

	@Override
	public void removeExpressions(IExpression[] expressions) {
		List<IExpression> removed = new ArrayList<>(expressions.length);
		synchronized (this) {
			if (fExpressions == null) {
				return;
			}
			for (IExpression expression : expressions) {
				if (fExpressions.remove(expression)) {
					removed.add(expression);
				}
			}
		}
		// dispose outside of the synchronized block
		if (!removed.isEmpty()) {
			for (IExpression expression : removed) {
				expression.dispose();
			}
			fireUpdate(removed.toArray(new IExpression[removed.size()]), REMOVED);
		}
	}

	@Override
	public void addExpressionListener(IExpressionListener listener) {
		if (fListeners == null) {
			fListeners = new ListenerList<>();
		}
		fListeners.add(listener);
	}

	@Override
	public void removeExpressionListener(IExpressionListener listener) {
		if (fListeners == null) {
			return;
		}
		fListeners.remove(listener);
	}

	/**
	 * The given watch expression has changed. Update the persisted
	 * expressions to store this change as indicated
	 *
	 * @param expression the changed expression
	 */
	protected void watchExpressionChanged(IWatchExpression expression) {
		boolean notify = false;
		synchronized (this) {
			if (fExpressions != null && fExpressions.contains(expression)) {
				notify = true;
			}
		}
		if (notify) {
			fireUpdate(new IExpression[]{expression}, CHANGED);
		}
	}

	/**
	 * Notifies listeners of the adds/removes/changes
	 *
	 * @param expressions expressions that were modified
	 * @param update update flags
	 */
	private void fireUpdate(IExpression[] expressions, int update){
		fireUpdate(expressions, update, -1);
	}

	/**
	 * Notifies listeners of the adds/removes/changes/insertions/moves
	 *
	 * @param expressions expressions that were modified
	 * @param update update flags
	 * @param index index where expressions were inserted/moved to or <code>-1</code>
	 */
	private void fireUpdate(IExpression[] expressions, int update, int index){
		// single listeners
		getExpressionNotifier().notify(expressions, update);

		// multi listeners
		getExpressionsNotifier().notify(expressions, update, index);
	}

	@Override
	public synchronized boolean hasExpressions() {
		return fExpressions != null && !fExpressions.isEmpty();
	}

	@Override
	public void addExpressionListener(IExpressionsListener listener) {
		if (fExpressionsListeners == null) {
			fExpressionsListeners = new ListenerList<>();
		}
		fExpressionsListeners.add(listener);
	}

	@Override
	public void removeExpressionListener(IExpressionsListener listener) {
		if (fExpressionsListeners == null) {
			return;
		}
		fExpressionsListeners.remove(listener);
	}

	private ExpressionNotifier getExpressionNotifier() {
		return new ExpressionNotifier();
	}

	/**
	 * Notifies an expression listener (single expression) in a safe runnable to
	 * handle exceptions.
	 */
	class ExpressionNotifier implements ISafeRunnable {

		private IExpressionListener fListener;
		private int fType;
		private IExpression fExpression;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during expression change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
				case INSERTED:
					fListener.expressionAdded(fExpression);
					break;
				case REMOVED:
					fListener.expressionRemoved(fExpression);
					break;
				case CHANGED:
					fListener.expressionChanged(fExpression);
					break;
				default:
					break;
			}
		}

		/**
		 * Notifies listeners of the add/change/remove
		 *
		 * @param expressions the expressions that have changed
		 * @param update the type of change
		 */
		public void notify(IExpression[] expressions, int update) {
			if (fListeners != null) {
				fType = update;
				for (IExpressionListener iExpressionListener : fListeners) {
					fListener = iExpressionListener;
					for (IExpression expression : expressions) {
						fExpression = expression;
						SafeRunner.run(this);
					}
				}
			}
			fListener = null;
			fExpression = null;
		}
	}

	/**
	 * Returns the expressions notifier
	 * @return the expressions notifier
	 */
	private ExpressionsNotifier getExpressionsNotifier() {
		return new ExpressionsNotifier();
	}

	/**
	 * Notifies an expression listener (multiple expressions) in a safe runnable
	 * to handle exceptions.
	 */
	class ExpressionsNotifier implements ISafeRunnable {

		private IExpressionsListener fListener;
		private int fType;
		private int fIndex;
		private IExpression[] fNotifierExpressions;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during expression change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case MOVED:
					// If the listener doesn't know about moves or the insertion location is unknown, do nothing.
					if (fIndex >= 0 && fListener instanceof IExpressionsListener2){
						((IExpressionsListener2)fListener).expressionsMoved(fNotifierExpressions, fIndex);
					}
					break;
				case INSERTED:
					// If the listener doesn't know about insertions or the insertion location is unknown, notify of an ADD
					if (fIndex >= 0 && fListener instanceof IExpressionsListener2){
						((IExpressionsListener2)fListener).expressionsInserted(fNotifierExpressions, fIndex);
					} else {
						fListener.expressionsAdded(fNotifierExpressions);
					}
					break;
				case ADDED:
					fListener.expressionsAdded(fNotifierExpressions);
					break;
				case REMOVED:
					fListener.expressionsRemoved(fNotifierExpressions);
					break;
				case CHANGED:
					fListener.expressionsChanged(fNotifierExpressions);
					break;
				default:
					break;
			}
		}

		/**
		 * Notifies listeners of the adds/changes/removes
		 *
		 * @param expressions the expressions that changed
		 * @param update the type of change
		 * @param index the index of the first change
		 */
		public void notify(IExpression[] expressions, int update, int index) {
			if (fExpressionsListeners != null) {
				fNotifierExpressions = expressions;
				fType = update;
				fIndex = index;
				for (IExpressionsListener iExpressionsListener : fExpressionsListeners) {
					fListener = iExpressionsListener;
					SafeRunner.run(this);
				}
			}
			fNotifierExpressions = null;
			fListener = null;
		}
	}
}
