/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation 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:
 *     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.Iterator;
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 fExpressions = null;
	
	/**
	 * List of expression listeners
	 */
	private ListenerList fListeners = null;
	
	/**
	 * List of expressions listeners (plural)
	 */
	private ListenerList fExpressionsListeners = null;
	
	/**
	 * Mapping of debug model identifiers (String) to
	 * expression delegate extensions (IConfigurationElement)
	 */
	private Map 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$
		IConfigurationElement[] configurationElements = extensionPoint.getConfigurationElements();
		for (int i = 0; i < configurationElements.length; i++) {
			IConfigurationElement element = configurationElements[i];
			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);
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#newWatchExpressionDelegate(java.lang.String)
	 */
	public IWatchExpressionDelegate newWatchExpressionDelegate(String debugModel) {
		try {
			IConfigurationElement element= (IConfigurationElement) fWatchExpressionDelegates.get(debugModel);
			if (element != null) {
				return (IWatchExpressionDelegate) element.createExecutableExtension(IConfigurationElementConstants.DELEGATE_CLASS);
			} 
			return null;
		} catch (CoreException e) {
			DebugPlugin.log(e);
			return null;
		}
	}

    /* (non-Javadoc)
     * @see org.eclipse.debug.core.IExpressionManager#hasWatchExpressionDelegate(java.lang.String)
     */
    public boolean hasWatchExpressionDelegate(String id) {
        IConfigurationElement element= (IConfigurationElement) 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 String[] {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);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#newWatchExpression(java.lang.String)
	 */
	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 (int i = 0; i < expressions.length; i++) {
			IExpression expression= expressions[i];
			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);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#addExpression(org.eclipse.debug.core.model.IExpression)
	 */
	public void addExpression(IExpression expression) {
		addExpressions(new IExpression[]{expression});
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#addExpressions(org.eclipse.debug.core.model.IExpression[])
	 */
	public void addExpressions(IExpression[] expressions) {
		List added = doAdd(expressions);
		if (!added.isEmpty()) {
			fireUpdate((IExpression[])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 doAdd(IExpression[] expressions) {
		List added = new ArrayList(expressions.length);
		synchronized (this) {
			if (fExpressions == null) {
				fExpressions = new Vector(expressions.length);
			}
			for (int i = 0; i < expressions.length; i++) {
				IExpression expression = expressions[i];
				if (fExpressions.indexOf(expression) == -1) {
					added.add(expression);
					fExpressions.add(expression);
				}				
			}
		}
		return added;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#getExpressions()
	 */
	public synchronized IExpression[] getExpressions() {
		if (fExpressions == null) {
			return new IExpression[0];
		}
		IExpression[] temp= new IExpression[fExpressions.size()];
		fExpressions.copyInto(temp);
		return temp;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#getExpressions(java.lang.String)
	 */
	public synchronized IExpression[] getExpressions(String modelIdentifier) {
		if (fExpressions == null) {
			return new IExpression[0];
		}
		ArrayList temp= new ArrayList(fExpressions.size());
		Iterator iter= fExpressions.iterator();
		while (iter.hasNext()) {
			IExpression expression= (IExpression) iter.next();
			String id= expression.getModelIdentifier();
			if (id != null && id.equals(modelIdentifier)) {
				temp.add(expression);
			}
		}
		return (IExpression[]) 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 added = null;
		List 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 (int i = 0; i < expressions.length; i++) {
					IExpression expression = expressions[i];
					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((IExpression[])added.toArray(new IExpression[added.size()]), ADDED);
			}
			return;
		}
		if (inserted != null) {
			if (!inserted.isEmpty()) {
				fireUpdate((IExpression[])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 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 (int i = 0; i < expressions.length; i++) {
				int removeIndex = fExpressions.indexOf(expressions[i]);
				if (removeIndex >= 0){
					movedExpressions.add(expressions[i]);
					if (removeIndex < insertionIndex){
						insertionIndex--;
					}
					fExpressions.remove(removeIndex);
				}
			}
			movedExpressionsArray = (IExpression[])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);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#removeExpression(org.eclipse.debug.core.model.IExpression)
	 */
	public void removeExpression(IExpression expression) {
		removeExpressions(new IExpression[] {expression});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#removeExpressions(org.eclipse.debug.core.model.IExpression[])
	 */
	public void removeExpressions(IExpression[] expressions) {
		List removed = new ArrayList(expressions.length);
		synchronized (this) {
			if (fExpressions == null) {
				return;
			}
			for (int i = 0; i < expressions.length; i++) {
				IExpression expression = expressions[i];
				if (fExpressions.remove(expression)) {
					removed.add(expression);
				}				
			}			
		}
		// dispose outside of the synchronized block
		Iterator iterator = removed.iterator();
		while (iterator.hasNext()) {
			((IExpression) iterator.next()).dispose();
		}
		if (!removed.isEmpty()) {
			fireUpdate((IExpression[])removed.toArray(new IExpression[removed.size()]), REMOVED);
		}
	}	
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#addExpressionListener(org.eclipse.debug.core.IExpressionListener)
	 */
	public void addExpressionListener(IExpressionListener listener) {
		if (fListeners == null) {
			fListeners = new ListenerList();
		}
		fListeners.add(listener);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#removeExpressionListener(org.eclipse.debug.core.IExpressionListener)
	 */
	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
	 * @param persist whether to persist the expressions
	 */
	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);
	}	

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#hasExpressions()
	 */
	public synchronized boolean hasExpressions() {
		return fExpressions != null && !fExpressions.isEmpty();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#addExpressionListener(org.eclipse.debug.core.IExpressionsListener)
	 */
	public void addExpressionListener(IExpressionsListener listener) {
		if (fExpressionsListeners == null) {
			fExpressionsListeners = new ListenerList();
		}
		fExpressionsListeners.add(listener);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IExpressionManager#removeExpressionListener(org.eclipse.debug.core.IExpressionsListener)
	 */
	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;

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
		 */
		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);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.ISafeRunnable#run()
		 */
		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;
			}			
		}

		/**
		 * 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;
				Object[] copiedListeners= fListeners.getListeners();
				for (int i= 0; i < copiedListeners.length; i++) {
					fListener = (IExpressionListener)copiedListeners[i];
					for (int j = 0; j < expressions.length; j++) {
						fExpression = expressions[j];
                        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;
		
		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
		 */
		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);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.ISafeRunnable#run()
		 */
		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;
			}			
		}

		/**
		 * 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;
				Object[] copiedListeners = fExpressionsListeners.getListeners();
				for (int i= 0; i < copiedListeners.length; i++) {
					fListener = (IExpressionsListener)copiedListeners[i];
                    SafeRunner.run(this);
				}
			}	
			fNotifierExpressions = null;
			fListener = null;				
		}
	}
}
