//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui;

import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.epf.authoring.gef.util.DiagramEditorUtil;
import org.eclipse.epf.authoring.ui.editors.EditorChooser;
import org.eclipse.epf.authoring.ui.providers.MethodEditorPageProvider;
import org.eclipse.epf.authoring.ui.providers.ProcessEditorPageProvider;
import org.eclipse.epf.common.plugin.AbstractPlugin;
import org.eclipse.epf.diagram.model.util.GraphicalDataManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.configuration.DefaultElementRealizer;
import org.eclipse.epf.library.configuration.ProcessAuthoringConfigurator;
import org.eclipse.epf.library.configuration.ProcessConfigurator;
import org.eclipse.epf.library.edit.ICommandListener;
import org.eclipse.epf.library.edit.IConfigurationApplicator;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.IConfiguratorFactory;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.command.MethodElementAddCommand;
import org.eclipse.epf.library.ui.LibraryUIManager;
import org.eclipse.epf.library.util.CopyAttachmentsToNewLocation;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.osgi.framework.BundleContext;


/**
 * The Authoring UI plug-in class.
 * 
 * @author Kelvin Low
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class AuthoringUIPlugin extends AbstractPlugin {

	// The shared plug-in instance.
	private static AuthoringUIPlugin plugin;

	/**
	 * Creates a new instance.
	 */
	public AuthoringUIPlugin() {
		super();
		plugin = this;
	}

	/**
	 * @see org.eclipse.epf.uma.core.plugin.AbstractPlugin#start(BundleContext context)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);

		// Prompt the user to select a Method Library.
		if ( LibraryService.getInstance().getCurrentMethodLibrary() == null ) {
			LibraryUIManager.getInstance().promptForMethodLibrary();
		}
		
		// Initialize ProcessAuthoringConfigurator
		ProcessAuthoringConfigurator.INSTANCE.getClass();
		
		// Initialize the move/paste command.
		MethodElementAddCommand
				.setResourceManager(new CopyAttachmentsToNewLocation());

		// Initialize the EditorChooser.
		EditorChooser.getInstance();

		// Load EditorPage Providers
		MethodEditorPageProvider.getInstance().loadProviders();
		ProcessEditorPageProvider.getInstance().loadProviders();
		
		// Set providers for library edit.
		Providers.setConfiguratorFactory(new IConfiguratorFactory() {
			public IConfigurator createConfigurator(MethodConfiguration config) {
				return new ProcessConfigurator(config, null, true);
			}
		});

		Providers
				.setConfigurationApplicator(new IConfigurationApplicator() {
					public Object getAttribute(VariabilityElement ve,
							EAttribute attribute, MethodConfiguration config) {
						return ConfigurationHelper.calcAttributeFeatureValue(
								ve, attribute, config);
					}

					public Object getReference(VariabilityElement ve,
							EReference ref, MethodConfiguration config) {
						if (ConfigurationHelper.is0nFeature(ref)) {
							return ConfigurationHelper.calc0nFeatureValue(ve,
									ref, new DefaultElementRealizer(config));
						} else if (ConfigurationHelper.is01Feature(ref)) {
							return ConfigurationHelper.calc01FeatureValue(ve,
									ref, new DefaultElementRealizer(config));
						}
						return null;
					}

					public Object getReference(ContentDescription desc, MethodElement owner,
							EReference ref, MethodConfiguration config) {

						List values = ConfigurationHelper.calc0nFeatureValue(
								desc, owner, ref, new DefaultElementRealizer(config));
						if (ref.isMany()) {
							return values;
						}
						if (values.isEmpty())
							return null;
						return values;
					}
					
					public Object getReference(MethodElement element,
							OppositeFeature feature, MethodConfiguration config) {
						List values = ConfigurationHelper.calc0nFeatureValue(element, feature, new DefaultElementRealizer(config));
						
						return values;
					}
					
					public Object resolve(Object object, MethodConfiguration config) {
						if(object instanceof MethodElement) {
							Object resolved = ConfigurationHelper.getCalculatedElement((MethodElement) object, config);
							if(resolved == null) {
								return object;
							}
							else {
								return resolved;
							}
						}
						else {
							return object;
						}
					}
				});
		Providers.setPreferenceStore(LibraryPlugin.getDefault()
				.getPreferenceStore());
		Providers.setAuthoringPlugin(this);

		List cmdListeners = GraphicalDataManager.getInstance()
				.getCommandListeners();
		cmdListeners.addAll(DiagramEditorUtil.getInstance().getVaryCommandListeners());
		for (Iterator iter = cmdListeners.iterator(); iter.hasNext();) {
			ICommandListener listener = (ICommandListener) iter.next();
			Providers.registerCommandListener(listener);
		}
		
		RefreshJob.getInstance().start();
	}

	/**
	 * @see org.eclipse.epf.uma.core.plugin.AbstractPlugin#start(BundleContext context)
	 */
	public void stop(BundleContext context) throws Exception {
		RefreshJob.getInstance().stop();
		
		super.stop(context);
		plugin = null;
	}

	/**
	 * Returns the shared plug-in instance.
	 */
	public static AuthoringUIPlugin getDefault() {
		return plugin;
	}

}