/******************************************************************************
 * Copyright (c) 2006, Intalio Inc.
 * 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:
 *     Intalio Inc. - initial API and implementation
 *******************************************************************************/

package org.eclipse.stp.bpmn.diagram.part;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.provider.EcoreItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.stp.bpmn.dnd.IEAnnotationDecorator;
import org.eclipse.stp.bpmn.dnd.IGenericEAnnotationDndHandler;
import org.eclipse.stp.bpmn.provider.BpmnItemProviderAdapterFactory;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

/**
 * @generated
 */
public class BpmnDiagramEditorPlugin extends AbstractUIPlugin {

    /**
     * @generated
     */
    public static final String ID = "org.eclipse.stp.bpmn.diagram"; //$NON-NLS-1$

    /**
     * @generated
     */
    public static final PreferencesHint DIAGRAM_PREFERENCES_HINT = new PreferencesHint(
            ID);

    /**
     * @generated
     */
    private static BpmnDiagramEditorPlugin instance;

    /**
     * @generated
     */
    private ComposedAdapterFactory adapterFactory;

    /**
     * The unique preference store.
     */
    public static IPreferenceStore PREF_STORE;

    /**
     * @generated
     */
    public BpmnDiagramEditorPlugin() {
    }

    /**
     * @generated
     */
    public void start(BundleContext context) throws Exception {
        super.start(context);
        instance = this;
        PreferencesHint.registerPreferenceStore(DIAGRAM_PREFERENCES_HINT,
                getPreferenceStore());
        adapterFactory = createAdapterFactory();
    }

    /**
     * Make sure there is a unique preference store here.
     */
    @Override
    public IPreferenceStore getPreferenceStore() {
        if (PREF_STORE == null) {
            PREF_STORE = super.getPreferenceStore();
        }
        return PREF_STORE;
    }

    /**
     * @generated
     */
    public void stop(BundleContext context) throws Exception {
        adapterFactory.dispose();
        adapterFactory = null;
        instance = null;
        super.stop(context);
    }

    /**
     * @generated
     */
    public static BpmnDiagramEditorPlugin getInstance() {
        return instance;
    }

    /**
     * @generated
     */
    protected ComposedAdapterFactory createAdapterFactory() {
        List factories = new ArrayList();
        fillItemProviderFactories(factories);
        return new ComposedAdapterFactory(factories);
    }

    /**
     * @generated
     */
    protected void fillItemProviderFactories(List factories) {
        factories.add(new BpmnItemProviderAdapterFactory());
        factories.add(new EcoreItemProviderAdapterFactory());
        factories.add(new ResourceItemProviderAdapterFactory());
        factories.add(new ReflectiveItemProviderAdapterFactory());
    }

    /**
     * @generated
     */
    public AdapterFactory getItemProvidersAdapterFactory() {
        return adapterFactory;
    }

    /**
     * @generated
     */
    public ImageDescriptor getItemImageDescriptor(Object item) {
        IItemLabelProvider labelProvider = (IItemLabelProvider) adapterFactory
                .adapt(item, IItemLabelProvider.class);
        if (labelProvider != null) {
            return ExtendedImageRegistry.getInstance().getImageDescriptor(
                    labelProvider.getImage(item));
        }
        return null;
    }

    /**
     * Returns an image descriptor for the image file at the given plug-in
     * relative path.
     * 
     * @generated
     * @param path
     *            the path
     * @return the image descriptor
     */
    public static ImageDescriptor getBundledImageDescriptor(String path) {
        return AbstractUIPlugin.imageDescriptorFromPlugin(ID, path);
    }

    /**
     * Respects images residing in any plug-in. If path is relative, then this
     * bundle is looked up for the image, otherwise, for absolute path, first
     * segment is taken as id of plug-in with image
     * 
     * @generated
     * @param path
     *            the path to image, either absolute (with plug-in id as first
     *            segment), or relative for bundled images
     * @return the image descriptor
     */
    public static ImageDescriptor findImageDescriptor(String path) {
        final IPath p = new Path(path);
        if (p.isAbsolute() && p.segmentCount() > 1) {
            return AbstractUIPlugin.imageDescriptorFromPlugin(p.segment(0), p
                    .removeFirstSegments(1).makeAbsolute().toString());
        } else {
            return getBundledImageDescriptor(p.makeAbsolute().toString());
        }
    }

    /**
     * Returns an image for the image file at the given plug-in relative path.
     * Client do not need to dispose this image. Images will be disposed
     * automatically.
     * 
     * @generated
     * @param path
     *            the path
     * @return image instance
     */
    public Image getBundledImage(String path) {
        Image image = getImageRegistry().get(path);
        if (image == null) {
            getImageRegistry().put(path, getBundledImageDescriptor(path));
            image = getImageRegistry().get(path);
        }
        return image;
    }

    /**
     * @generated
     */
    public void logError(String error) {
        logError(error, null);
    }

    /**
     * @param throwable
     *            actual error or null could be passed
     * @generated
     */
    public void logError(String error, Throwable throwable) {
        if (error == null && throwable != null) {
            error = throwable.getMessage();
        }
        getLog().log(
                new Status(IStatus.ERROR, BpmnDiagramEditorPlugin.ID,
                        IStatus.OK, error, throwable));
        debug(error, throwable);
    }

    /**
     * @generated
     */
    public void logInfo(String message) {
        logInfo(message, null);
    }

    /**
     * @param throwable
     *            actual error or null could be passed
     * @generated
     */
    public void logInfo(String message, Throwable throwable) {
        if (message == null && message != null) {
            message = throwable.getMessage();
        }
        getLog().log(
                new Status(IStatus.INFO, BpmnDiagramEditorPlugin.ID,
                        IStatus.OK, message, throwable));
        debug(message, throwable);
    }

    /**
     * @generated
     */
    private void debug(String message, Throwable throwable) {
        if (!isDebugging()) {
            return;
        }
        if (message != null) {
            System.err.println(message);
        }
        if (throwable != null) {
            throwable.printStackTrace();
        }
    }

    /**
     * @notgenerated
     */
    public static final String EANNOTATION_DND_HANDLER_EXTENSION_POINT = ID + 
    				".EAnnotationDragAndDrop";
    
    /**
     * @notgenerated
     */
    public static final String EANNOTATION_DECORATOR_EXTENSION_POINT = ID + 
    				".EAnnotationDecorator";
    /**
     * @notgenerated
     * returns the class implementing the extension point 
     * for the generic drag and drop of an Eannotation 
     */
    public IGenericEAnnotationDndHandler getEAnnotationDragAndDropHandler(
    		String annotationSource) {
    	IExtensionRegistry registry = Platform.getExtensionRegistry();
    	// get extension point that defines Generators
    	IExtensionPoint point = registry
    	.getExtensionPoint(EANNOTATION_DND_HANDLER_EXTENSION_POINT);
    	if (point != null) {
    		IExtension[] extensions = point.getExtensions();
    		for (int i = 0; i < extensions.length; i++) {
    			IConfigurationElement[] configElems = extensions[i]
    			       .getConfigurationElements();
    			for (int j = configElems.length - 1; j >= 0; j--) {
    				try {
    					if (
    			configElems[j].getAttribute("source") != null &&
    			configElems[j].getAttribute("source").
    				equals(annotationSource)) {
    						return (IGenericEAnnotationDndHandler) configElems[j]
    						       .createExecutableExtension("class");
    					}
    				} catch (Exception e) {
    					logError(e.getMessage(),e);
    					continue;
    				}
    			}
    		}
    	}
    	return null;
    }
    
    /**
     * @notgenerated
     * returns the class implementing the extension point 
     * for the generic drag and drop of an Eannotation 
     */
    public IEAnnotationDecorator getEAnnotationDecorator(
    		String annotationSource) {
    	IExtensionRegistry registry = Platform.getExtensionRegistry();
    	// get extension point that defines Generators
    	IExtensionPoint point = registry
    	.getExtensionPoint(EANNOTATION_DECORATOR_EXTENSION_POINT);
    	if (point != null) {
    		IExtension[] extensions = point.getExtensions();
    		for (int i = 0; i < extensions.length; i++) {
    			IConfigurationElement[] configElems = extensions[i]
    			       .getConfigurationElements();
    			for (int j = configElems.length - 1; j >= 0; j--) {
    				try {
    					if (
    			configElems[j].getAttribute("source") != null &&
    			configElems[j].getAttribute("source").
    				equals(annotationSource)) {
    						return (IEAnnotationDecorator) configElems[j]
    						       .createExecutableExtension("class");
    					}
    				} catch (Exception e) {
    					logError(e.getMessage(),e);
    					continue;
    				}
    			}
    		}
    	}
    	return null;
    }
}

