/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * 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:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.ui.editors.layout;

import java.util.HashMap;
import java.util.Map;

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.Platform;
import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
import org.eclipse.gef.palette.CreationToolEntry;
import org.eclipse.gef.palette.MarqueeToolEntry;
import org.eclipse.gef.palette.PaletteContainer;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.SelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.gef.ui.palette.PaletteCustomizer;
import org.eclipse.jface.resource.ImageDescriptor;

import org.maskat.core.layout.custom.ComponentRegistry;
import org.maskat.core.layout.custom.UnknownComponentClass;
import org.maskat.ui.ISharedImages;
import org.maskat.ui.MaskatUIPlugin;
import org.maskat.ui.editors.layout.requests.BeanCreationFactory;

public class PluggablePaletteCustomizer extends PaletteCustomizer {

	private static ImageDescriptor DEFAULT_IMAGE_DESCRIPTOR = MaskatUIPlugin
			.getImageDescriptor(ISharedImages.IMG_COMPONENTICON);
	
	private PaletteRoot paletteRoot;

	private Map entries;

	public PluggablePaletteCustomizer() {
		super();
		paletteRoot = new PaletteRoot();
		entries = new HashMap();
		initializePalette();
		revertToSaved();
	}

	public PaletteRoot getPaletteRoot() {
		return paletteRoot;
	}

	private void initializePalette() {
		PaletteGroup group = new PaletteGroup("tools"); //$NON-NLS-1$
		ToolEntry entry = new SelectionToolEntry();
		paletteRoot.setDefaultEntry(entry);
		group.add(entry);
		group.add(new MarqueeToolEntry());
		paletteRoot.add(group);

		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(
				MaskatUIPlugin.PLUGIN_ID, "paletteEntries");
		IExtension[] extensions = point.getExtensions();

		/* First we add palette containers */
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i].getConfigurationElements();
			for (int j = 0; j < elements.length; j++) {
				if ("drawer".equals(elements[j].getName())) {
					addPaletteDrawer(elements[j]);
				}
			}
		}

		/* Then add palette entries */
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i].getConfigurationElements();
			for (int j = 0; j < elements.length; j++) {
				if ("creationTool".equals(elements[j].getName())) {
					addCreationToolEntry(elements[j]);
				}
			}
		}
	}
	
	private void addPaletteDrawer(IConfigurationElement element) {
		PaletteDrawer drawer = new PaletteDrawer(element.getAttribute("label"),
				MaskatUIPlugin.getImageDescriptor(element, "icon"));
		String id = element.getAttribute("id");
		drawer.setId(id);
		entries.put(id, drawer);
		
		String path = element.getAttribute("path");
		if (path != null && entries.containsKey(path)) {
			PaletteEntry entryForPath = (PaletteEntry) entries.get(path);
			if (entryForPath instanceof PaletteContainer) {
				((PaletteContainer) entryForPath).add(drawer);
			} else {
				entryForPath.getParent().add(drawer);
			}
		} else {
			paletteRoot.add(drawer);
		}
	}

	private void addCreationToolEntry(IConfigurationElement element) {
		String namespaceURI = element.getAttribute("namespaceURI");
		String name = element.getAttribute("name");
		CreationFactory factory = null;

		try {
			if (element.getAttribute("factory") != null) {
				factory = (CreationFactory) element.createExecutableExtension("factory");
			} else {
				IConfigurationElement[] children = element.getChildren("property");
				Map properties = null;
				if (children != null) {
					properties = new HashMap();
					for (int i = 0; i < children.length; i++) {
						String key = children[i].getAttribute("name");
						String value = children[i].getAttribute("value");
						properties.put(key, value);
					}
				}
				Object type = ComponentRegistry.getComponentType(namespaceURI, name);
				type = type == null ? new UnknownComponentClass() : type;
				factory = new BeanCreationFactory(type, properties);
			}
//		} catch (UnknownComponentException e) {
//			IStatus status = new Status(IStatus.ERROR, MaskatUIPlugin.PLUGIN_ID, 0,
//					"Unknown component type: " + namespaceURI + "#" + name, e);
//			MaskatUIPlugin.log(status);
		} catch (CoreException e) {
			MaskatUIPlugin.log(e.getStatus());
		}

		ImageDescriptor iconSmall = MaskatUIPlugin.getImageDescriptor(element, "iconSmall"); 
		ImageDescriptor iconLarge = MaskatUIPlugin.getImageDescriptor(element, "iconLarge");
		CreationToolEntry entry = new CombinedTemplateCreationEntry(
				element.getAttribute("label"),
				element.getAttribute("description"),
				factory,
				(iconSmall != null) ? iconSmall : DEFAULT_IMAGE_DESCRIPTOR,
				(iconLarge != null) ? iconLarge : DEFAULT_IMAGE_DESCRIPTOR);
		
		String id = element.getAttribute("id");
		entry.setId(id);
		entries.put(id, entry);

		String path = element.getAttribute("path");
		if (path != null && entries.containsKey(path)) {
			PaletteEntry entryForPath = (PaletteEntry) entries.get(path);
			if (entryForPath instanceof PaletteContainer) {
				((PaletteContainer) entryForPath).add(entry);
			} else {
				entryForPath.getParent().add(entry);
			}
		} else {
			paletteRoot.add(entry);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.ui.palette.PaletteCustomizer#revertToSaved()
	 */
	public void revertToSaved() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.ui.palette.PaletteCustomizer#save()
	 */
	public void save() {
	}

}
