/**
 * File:    WEExternalSheetManager.java
 * Created: 23.09.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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:
 *    Christian Saad, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.editors.pages.externalSheet.internal;

import java.util.HashMap;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jwt.we.PluginProperties;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.editors.pages.externalSheet.IWEExternalSheetProvider;
import org.eclipse.jwt.we.misc.extensions.ExtensionsHelper;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IEditorPart;


/**
 * This class contains the management code for external sheets. It keeps a list of all
 * registered sheets and offers the possibility to load a sheet into an editor.
 * 
 * @version $Id: WEExternalSheetManager.java,v 1.4 2009-12-18 13:06:38 mdutoo Exp $
 * @author Christian Saad, Programming distributed Systems Lab, University of Augsburg,
 *         Germany, www.ds-lab.org
 */
public class WEExternalSheetManager
{

	/**
	 * A Logger.
	 */
	private static final Logger logger = Logger.getLogger(WEExternalSheetManager.class);

	/**
	 * The instance.
	 */
	private static WEExternalSheetManager myinstance = null;

	/**
	 * A map of all external editor sheets found in the extension point.
	 */
	private HashMap<String, IConfigurationElement> externalEditorSheets;


	/**
	 * Returns the singleton instance.
	 */
	public static WEExternalSheetManager getInstance()
	{
		if (myinstance == null)
			myinstance = new WEExternalSheetManager();
		return myinstance;
	}


	/**
	 * Load all sheets descriptions defined via extension point into the internal map.
	 * This is done only once on initializing.
	 */
	private void loadExternalSheetsIntoMap()
	{
		String extension_point_id = PluginProperties.extension_point_sheet;

		logger.debug("get sheets from extension point " + extension_point_id); //$NON-NLS-1$

		try
		{
			externalEditorSheets = new HashMap<String, IConfigurationElement>();

			// first get all extending classes and their directories get the registry and
			// the extension point
			IConfigurationElement[] confElements = ExtensionsHelper
					.findConfigurationElements(extension_point_id);

			// exit if there are no extensions registered
			if (confElements == null)
			{
				logger.debug("no external sheets found"); //$NON-NLS-1$
				return;
			}

			// read external sheets from extension point
			for (IConfigurationElement point : confElements)
			{
				// read the attributes from the extension point
				String externalSheetTitle = point.getAttribute("title"); //$NON-NLS-1$

				externalEditorSheets.put(externalSheetTitle, point);

				logger.info("JWT Extension - found SHEET at " + extension_point_id + ": " //$NON-NLS-1$ //$NON-NLS-2$
						+ externalSheetTitle);
			}

		}
		catch (Exception e)
		{
			logger.warning("error loading external sheets", e); //$NON-NLS-1$
		}
	}


	/**
	 * Returns the map of external sheets extension points registered by their title.
	 */
	public HashMap<String, IConfigurationElement> getExternalSheets()
	{
		if (externalEditorSheets == null)
		{
			loadExternalSheetsIntoMap();
		}

		return externalEditorSheets;
	}


	/**
	 * Loads the external sheet with the given title. If a sheet with this ID already
	 * exists and the sheet type is not *multiple*, the "old" sheet is activated.
	 * 
	 * @param sheetTitle
	 */
	public void displayExternalSheet(WEEditor editor, String sheetTitle)
	{
		try
		{
			// get the sheet from the map
			IConfigurationElement point = getExternalSheets().get(sheetTitle);

			// if the sheet may NOT be opened multiple times, check if the sheet is
			// already open and activate if so
			if (point.getAttribute("multiple").equals("false")) //$NON-NLS-1$ //$NON-NLS-2$
			{
				for (int i = 0; i < editor.getPageCount(); i++)
				{
					if (editor.getTabFolder().getItem(i).getText().equals(sheetTitle))
					{
						editor.activatePage(i);
						return;
					}
				}
			}

			// get the external sheet provider
			IWEExternalSheetProvider externalSheetProvider = (IWEExternalSheetProvider) point
					.createExecutableExtension("class"); //$NON-NLS-1$
			externalSheetProvider.init(editor);
			Object externalSheet = externalSheetProvider.getExternalSheet();
			externalSheetProvider = null;

			// insert the new control/editorpart
			int pageID = editor.getActivePage() == -1 ? editor.getPageCount() : editor
					.getActivePage() + 1;
			if (externalSheet instanceof IEditorPart)
			{
				editor.addPage(pageID, (IEditorPart) externalSheet, editor
						.getEditorInput());
			}
			else if (externalSheet instanceof Control)
			{
				editor.addPage(pageID, (Control) externalSheet);
			}

			// set the title of the new sheet
			editor.getTabFolder().getItem(pageID).setText(sheetTitle);

			// make closable?
			if (point.getAttribute("closable").equals("true")) //$NON-NLS-1$ //$NON-NLS-2$
			{
				editor.getTabFolder().getItem(pageID).setShowClose(true);
			}

			editor.activatePage(pageID);
		}
		catch (Exception e)
		{
			logger.warning("error loading external sheets", e); //$NON-NLS-1$
			e.printStackTrace();
		}
	}

}
