/**
 * File:    PropertySheetPageExtensionPoint.java
 * Created: 11.07.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * Open Wide SA, France <www.openwide.fr>
 *
 * 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
 *
 *    Marc Dutoo, Open Wide, France
 *      - Creation and Implementation
 *******************************************************************************/

package org.eclipse.jwt.we.editors.properties.extension.internal;

import java.util.ArrayList;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jwt.we.Plugin;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.editors.properties.singlePage.ModelPropertySheetPage;
import org.eclipse.jwt.we.editors.properties.tabbedPage.TabbedModelPropertySheetPage;
import org.eclipse.jwt.we.misc.extensions.ExtensionsHelper;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.views.properties.IPropertySheetPage;


/**
 * Extension point related code to get the custom propertySheetPage, or the default one if
 * none. Uses PropertySheetPageDescriptor to remember its description after reading it
 * from registry.
 * 
 * @version $Id: PropertySheetPageExtensionPoint.java,v 1.1 2009/03/16 17:17:47 mistria
 *          Exp $
 * @author Marc Dutoo, Open Wide SA, France <www.openwide.fr>
 */
public class PropertySheetPageExtensionPoint
{

	/** The extension point, read from the property file */
	public static final String EXTENSION_POINT = Plugin.getId() + ".propertySheet"; //$NON-NLS-1$
	private static final String CLASS = "class"; //$NON-NLS-1$
	private static final String PROPERTY_TABS_EXTENSION_POINT = "org.eclipse.ui.views.properties.tabbed.propertyTabs"; //$NON-NLS-1$

	private static Logger log = Logger.getLogger(PropertySheetPageExtensionPoint.class);

	/** Found configured propertySheetPageDescriptor */
	private static PropertySheetPageDescriptor propertySheetPageDescriptor = null;
	private static boolean initialized = false;


	/**
	 * Inits. Processes ext point and finds configured rootAdapterFactoryDescriptor if
	 * any, else uses the default one.
	 */
	private synchronized static void init()
	{
		if (!initialized)
		{
			try
			{
				processExtensionPoint();
			}
			catch (WorkbenchException ex)
			{
				log
						.severe("Error processing extension point for custom RootAdapterFactory"); //$NON-NLS-1$
			}

			if (propertySheetPageDescriptor == null)
			{
				// default property sheet page case TODO replace with externalized conf
				// later
				propertySheetPageDescriptor = createDefaultPropertySheetPageDescriptor();
			}

			initialized = true;
		}
	}


	/**
	 * Inits
	 * 
	 * @return a new custom rootAdapterFactory, according to the configured
	 *         propertySheetPageDescriptor, or the default one if none
	 */
	public static IPropertySheetPage createPropertySheetPage(WEEditor weEditor)
	{
		init();

		if (propertySheetPageDescriptor != null)
		{
			return propertySheetPageDescriptor.createPropertySheetPage(weEditor);
		}

		return null;
	}


	/**
	 * Process the extension point i.e. get the configured rootAdapterFactoryDescriptor.
	 * 
	 * @throws WorkbenchException
	 */
	private static void processExtensionPoint() throws WorkbenchException
	{
		log.debug("Processing extension point " + EXTENSION_POINT); //$NON-NLS-1$

		IConfigurationElement[] confElements = ExtensionsHelper
				.findConfigurationElements(EXTENSION_POINT);

		// get custom root adapter factory if any
		if (confElements != null && confElements.length == 1)
		{
			IConfigurationElement confElement = confElements[0];

			try
			{
				String pageClassName = confElement.getAttribute(CLASS);
				String extensionName = confElement.getDeclaringExtension()
						.getNamespaceIdentifier();
				Class<?> pageClass = Platform.getBundle(extensionName).loadClass(
						pageClassName);
				propertySheetPageDescriptor = new ClassPropertySheetPageDescriptor(
						pageClass);
			}
			catch (Exception e)
			{ // ClassNotFoundException, InvocationTargetException TODO nosuchMeth
				log.severe("Error loading custom property sheet", e); //$NON-NLS-1$
			}

			if (propertySheetPageDescriptor != null)
			{
				log
						.info("JWT Property Sheet extension - found custom property sheet page at " //$NON-NLS-1$
								+ EXTENSION_POINT + ": " + propertySheetPageDescriptor); //$NON-NLS-1$
			}

		}
		else
		{
			// NB. logging at info level because rightly reverts to default behaviour
			// (default, single tab ModelPropertySheetPage property sheet) afterwards,
			// see bug #277673
			log.info("JWT Extension at " + EXTENSION_POINT //$NON-NLS-1$
					+ " - found no or more than one custom propertySheetPageDescriptor"); //$NON-NLS-1$
		}
	}


	/**
	 * Default property sheet page case. Code migrated from WEEditor.
	 * 
	 * @return
	 */
	public static final PropertySheetPageDescriptor createDefaultPropertySheetPageDescriptor()
	{
		// look for registered property tabs
		IConfigurationElement[] allElements = ExtensionsHelper
				.findConfigurationElements(PROPERTY_TABS_EXTENSION_POINT);

		// consider only JWT property sheet pages
		ArrayList<IConfigurationElement> confElements = new ArrayList<IConfigurationElement>();
		for (IConfigurationElement point : allElements)
		{
			String contributorId = point.getAttribute("contributorId");
			if (contributorId != null
					&& contributorId.equals("org.eclipse.jwt.we.editors.WEEditor"))
			{
				confElements.add((IConfigurationElement) point);
			}
		}

		// check if more than the one standard tab is registered
		if (confElements.size() == 1)
		{
			// only the standard tab was found -> use "old" property sheet
			log
					.info("JWT Extension - no additional property tabs, using standard propertyview"); //$NON-NLS-1$

			// NB. new ClassPropertySheetPageDescriptor(ModelPropertySheetPage.class)
			// would also work
			return new PropertySheetPageDescriptor()
			{
				public IPropertySheetPage createPropertySheetPage(WEEditor weEditor)
				{
					return new ModelPropertySheetPage(weEditor.getAdapterFactory());
				}
			};

		}
		else
		{
			// additional tabs were found -> use new multitab property sheet
			log
					.info("JWT Extension - found additional property tabs, using multitab propertyview"); //$NON-NLS-1$

			for (IConfigurationElement point : confElements)
			{
				log.info("JWT Extension - found PROPERTYTAB at " //$NON-NLS-1$
						+ PROPERTY_TABS_EXTENSION_POINT + ": " //$NON-NLS-1$
						+ point.getChildren()[0].getAttribute("label")); //$NON-NLS-1$
			}

			// NB. new TabbedModelPropertySheetPage(ModelPropertySheetPage.class) would
			// also work
			return new PropertySheetPageDescriptor()
			{

				public IPropertySheetPage createPropertySheetPage(WEEditor weEditor)
				{
					return new TabbedModelPropertySheetPage(weEditor);
				}
			};
		}
	}

}
