/******************************************************************************
 * Copyright (c) 2002, 2008 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.gmf.runtime.diagram.ui.services.palette;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.palette.PaletteContainer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.PanningSelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gmf.runtime.common.core.service.ExecutionStrategy;
import org.eclipse.gmf.runtime.common.core.service.IOperation;
import org.eclipse.gmf.runtime.common.core.service.IProvider;
import org.eclipse.gmf.runtime.common.core.service.Service;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.common.ui.services.util.ActivityFilterProviderDescriptor;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.palette.ContributeToPaletteOperation;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.palette.PaletteProviderConfiguration;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.gef.ui.internal.palette.PaletteSeparator;
import org.eclipse.gmf.runtime.gef.ui.internal.palette.PaletteToolbar;
import org.eclipse.ui.IEditorPart;

/**
 * @author melaasar
 *
 * A service to contributes to the palette of a given editor with a given content
 */
public class PaletteService extends Service implements IPaletteProvider {

	/**
	 * @author schafe
	 * @author melaasar
	 *
	 * A descriptor for palette providers defined by a configuration
	 * element.
	 */
	protected static class ProviderDescriptor
		extends ActivityFilterProviderDescriptor {

		/** the provider configuration parsed from XML */
		private PaletteProviderConfiguration providerConfiguration;

		/**
		 * Constructs a <code>ISemanticProvider</code> descriptor for
		 * the specified configuration element.
		 * 
		 * @param element The configuration element describing the provider.
		 */
		public ProviderDescriptor(IConfigurationElement element) {
			super(element);

			this.providerConfiguration =
				PaletteProviderConfiguration.parse(element);
			Assert.isNotNull(providerConfiguration);
		}

		/**
		 * @see org.eclipse.gmf.runtime.common.core.service.IProvider#provides(org.eclipse.gmf.runtime.common.core.service.IOperation)
		 */
		public boolean provides(IOperation operation) {
			if (!super.provides(operation)) {
				return false;
			}
			if (!policyInitialized){
				policy = getPolicy();
				policyInitialized = true;
			}
			if (policy != null)
				return policy.provides(operation);
			
			if (operation instanceof ContributeToPaletteOperation) {
				ContributeToPaletteOperation o =
					(ContributeToPaletteOperation) operation;

				return providerConfiguration.supports(
					o.getEditor(),
					o.getContent());
			}
			return false;
		}

		/**
		 * @see org.eclipse.gmf.runtime.common.core.service.Service.ProviderDescriptor#getProvider()
		 */
		public IProvider getProvider() {
			if (provider == null) {
				IProvider newProvider = super.getProvider();
				if (provider instanceof IPaletteProvider) {
					IPaletteProvider defaultProvider =
						(IPaletteProvider) newProvider;
					defaultProvider.setContributions(getElement());
				}
				return newProvider;
			}
			return super.getProvider();
		}
	}

	
	/**
	 * Sets contribution
	 * Empty because contributions are stored in the providers
	 * 
	 * @param configElement
	 */
	public void setContributions(IConfigurationElement configElement) {
	//  
	}

	/** the singleton instance of the palette service */
	private final static PaletteService instance = new PaletteService();

	static {
		instance.configureProviders(DiagramUIPlugin.getPluginId(), "paletteProviders"); //$NON-NLS-1$
	}

	/** the standard group id */
	public final static String GROUP_STANDARD = "standardGroup"; //$NON-NLS-1$

	/** the standard separator id */
	public final static String SEPARATOR_STANDARD = "standardSeparator"; //$NON-NLS-1$

	/** the standard separator id */
	public final static String TOOL_SELECTION = "selectionTool"; //$NON-NLS-1$

	/**
	 *  Creates a new instance of the Palette Service
	 */
	protected PaletteService() {
		super();
	}

	/**
	 * gets the singleton instance
	 * @return <code>PaletteService</code>
	 */
	public static PaletteService getInstance() {
		return instance;
	}

	/**
	 * @see org.eclipse.gmf.runtime.common.core.service.Service#newProviderDescriptor(org.eclipse.core.runtime.IConfigurationElement)
	 */
	protected Service.ProviderDescriptor newProviderDescriptor(
		IConfigurationElement element) {
		return new ProviderDescriptor(element);
	}

	/**
	 * @see org.eclipse.gmf.runtime.diagram.ui.services.palette.IPaletteProvider#contributeToPalette(org.eclipse.ui.IEditorPart, java.lang.Object, org.eclipse.gef.palette.PaletteRoot, Map)
	 */
	public void contributeToPalette(
		IEditorPart editor,
		Object content,
		PaletteRoot root, Map predefinedEntries) {

	    PaletteToolbar standardGroup = new PaletteToolbar(GROUP_STANDARD, DiagramUIMessages.StandardGroup_Label);
		standardGroup.setDescription(DiagramUIMessages.StandardGroup_Description);
		root.add(standardGroup);

		PaletteSeparator standardSeparator = new PaletteSeparator(SEPARATOR_STANDARD);
		standardGroup.add(standardSeparator);

		ToolEntry selectTool = new PanningSelectionToolEntry();
		selectTool.setId(TOOL_SELECTION);
		selectTool.setToolClass(SelectionToolEx.class);
		standardGroup.add(selectTool);
		root.setDefaultEntry(selectTool);

		execute(new ContributeToPaletteOperation(editor, content, root, predefinedEntries));       
	}


    /**
	 * Executes the palette operation using 
	 * the REVERSE execution strategy.
	 * 
	 * @param operation
	 * @return List of results
	 */
	private List execute(IOperation operation) {
		return execute(ExecutionStrategy.REVERSE, operation);
	}

	/**
	 * Creates default palette root.
	 * 
	 * @param editor
	 *            the editor
	 * @param content
	 *            the palette content
	 * @return a new palette root with contributions from all providers
	 */
	public PaletteRoot createPalette(
		final IEditorPart editor,
		final Object content) {
		final PaletteRoot root = new PaletteRoot();
		try {
			IEditingDomainProvider provider = (IEditingDomainProvider) editor
				.getAdapter(IEditingDomainProvider.class);
			if (provider != null) {
				EditingDomain domain = provider.getEditingDomain();
				if (domain instanceof TransactionalEditingDomain) {
					((TransactionalEditingDomain) domain)
						.runExclusive(new Runnable() {

							public void run() {
								contributeToPalette(editor, content, root, new HashMap());
							}
						});
				}
			}
		} catch (Exception e) {
			Trace.catching(DiagramUIPlugin.getInstance(),
					DiagramUIDebugOptions.EXCEPTIONS_CATCHING, PaletteService.class,
					"createPalette()", //$NON-NLS-1$
					e);
		}
		return root;
	}
	
	/**
	 * Updates the palette root given.
	 * 
	 * @param existingRoot
	 *            existing palette root in which to add/remove entries that are
	 *            now provided for or no longer provided for
	 * @param editor
	 *            the editor
	 * @param content
	 *            the palette content
	 */
	public void updatePalette(
		PaletteRoot existingRoot,
		final IEditorPart editor,
		final Object content) {
		
		PaletteRoot newRoot = createPalette(editor, content);
		updatePaletteContainerEntries(existingRoot, newRoot);
	}
	
	/**
	 * Updates the children of an existing palette container to match the
	 * palette entries in a new palette container by adding or removing new
	 * palette entries only. This method works recursively on any children that
	 * are palette container entries. Existing leaf palette entries that are to
	 * be kept remain the same -- they are not replaced with the new palette
	 * entry. This is so that palette state (such as whether a drawer is pinned
	 * or expanded) can be preserved when the palette is updated.
	 * 
	 * @param existingContainer
	 *            the palette container to be updated with new entries, have
	 *            obsolete entries removed, and whose existing entries will
	 *            remain the same
	 * @param newContainer
	 *            the new palette entries
	 */
	private void updatePaletteContainerEntries(
			PaletteContainer existingContainer, PaletteContainer newContainer) {

		HashMap existingEntryIds = new HashMap();
		for (Iterator iter = existingContainer.getChildren().iterator(); iter
			.hasNext();) {
			PaletteEntry entry = (PaletteEntry) iter.next();
			existingEntryIds.put(entry.getId(), entry);
		}

		int nextNewIndex = 0;
		// cycle through the new entries
		for (Iterator iter = newContainer.getChildren().iterator(); iter
			.hasNext();) {
			PaletteEntry newEntry = (PaletteEntry) iter.next();

			PaletteEntry existingEntry = (PaletteEntry) existingEntryIds
				.get(newEntry.getId());
			if (existingEntry != null) { // is already in existing container
				// update the index
				nextNewIndex = existingContainer.getChildren()
					.indexOf(existingEntry) + 1;

				// remove the entry that was just updated from the map
				existingEntryIds.remove(existingEntry.getId());

				if (existingEntry instanceof PaletteContainer
					&& newEntry instanceof PaletteContainer) {
					// look for new/deleted entries in
					// palette containers
					updatePaletteContainerEntries(
						(PaletteContainer) existingEntry,
						(PaletteContainer) newEntry);
				}
			} else { // this is a new entry that did not previously exist
				existingContainer.add(nextNewIndex++, newEntry);
			}
		}

		// remove existing entries that were not found in the new container
		for (Iterator iter = existingEntryIds.values().iterator(); iter
			.hasNext();) {
			PaletteEntry entry = (PaletteEntry) iter.next();
			existingContainer.remove(entry);
		}

	}
	
}
