/*******************************************************************************
 * Copyright (c) 2001, 2004 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 API and implementation
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.ui.internal.extension;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.wst.sse.ui.extensions.breakpoint.IBreakpointProvider;
import org.eclipse.wst.sse.ui.extensions.breakpoint.SourceEditingTextTools;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.osgi.framework.Bundle;


/**
 * Reads breakpoint extension registory and returns breakpoint provider
 * instances
 */
public class BreakpointProviderBuilder extends RegistryReader {

	private static final String ATT_CLASS = "class"; //$NON-NLS-1$
	//private static final String ATT_ID = "id"; //$NON-NLS-1$
	private static final String ATT_CONTENT_TYPES = "contentTypes"; //$NON-NLS-1$
	private static final String ATT_EXTENSIONS = "extensions"; //$NON-NLS-1$
	private static BreakpointProviderBuilder instance;
	private static final String PL_BREAKPOINT = "breakpoint"; //$NON-NLS-1$

	private static final String PLUGIN_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$

	private static final String TAG_BREAKPOINT_CONTRIBUTION = "breakpointContribution"; //$NON-NLS-1$
	private static final String TAG_PROVIDER = "provider"; //$NON-NLS-1$

	/*
	 * Creates an executable extension. @param element the config element
	 * defining the extension @param classAttribute the name of the attribute
	 * carrying the class @return the extension object @throws CoreException
	 */
	static Object createExecutableExtension(final IConfigurationElement element, final String classAttribute) throws CoreException {
		return element.createExecutableExtension(classAttribute);
	}

	/**
	 * Creates an extension. If the extension plugin has not been loaded a
	 * busy cursor will be activated during the duration of the load.
	 * 
	 * @param element
	 *            the config element defining the extension
	 * @param classAttribute
	 *            the name of the attribute carrying the class
	 * @return the extension object
	 * @throws CoreException
	 */
	public static Object createExtension(final IConfigurationElement element, final String classAttribute) {
		// If plugin has been loaded create extension.
		// Otherwise, show busy cursor then create extension.
		final Object[] result = new Object[1];
		String pluginId = element.getDeclaringExtension().getNamespace();
		Bundle bundle = Platform.getBundle(pluginId);
		if (bundle.getState() == Bundle.ACTIVE) {
			try {
				result[0] = createExecutableExtension(element, classAttribute);
			} catch (Exception e) {
				handleCreateExecutableException(result, e);
			}
		} else {
			BusyIndicator.showWhile(null, new Runnable() {
				public void run() {
					try {
						result[0] = createExecutableExtension(element, classAttribute);
					} catch (CoreException e) {
						handleCreateExecutableException(result, e);
					}
				}
			});

		}
		return result[0];
	}

	/**
	 * returns singleton instance of BreakpointProviderBuilder
	 * 
	 * @return BreakpointProviderBuilder
	 */
	public synchronized static BreakpointProviderBuilder getInstance() {
		if (instance == null) {
			instance = new BreakpointProviderBuilder();
		}
		return instance;
	}

	/**
	 * @param result
	 * @param e
	 */
	private static void handleCreateExecutableException(Object[] result, Throwable e) {
		Logger.logException(e);
		result[0] = null;

	}

	protected List cache;
	private Map map = new HashMap();

	protected String targetContributionTag;

	/*
	 * Constructor
	 */
	private BreakpointProviderBuilder() {
		super();
	}

	/*
	 * Creates a breakpoint provider object to given element @param element
	 * configuration element object @return IBreakpointProvider
	 */
	protected IBreakpointProvider createBreakpointProvider(IConfigurationElement element) {
		Object obj = createExtension(element, ATT_CLASS);
		if (obj == null)
			return null;
		return (obj instanceof IBreakpointProvider) ? (IBreakpointProvider) obj : null;
	}

	/*
	 * Creates an array of breakpoint providers matching the given key to the
	 * value of the IConfigurationElement attribute "attrName" @return
	 * IBreakpointProvider[]
	 */
	protected IBreakpointProvider[] createBreakpointProviders(String attrName, String key) {
		if (cache == null)
			return new IBreakpointProvider[0];

		final int num = cache.size();
		if (num == 0)
			return new IBreakpointProvider[0];

		IBreakpointProvider[] bp = new IBreakpointProvider[num];
		int j = 0;
		for (int i = 0; i < num; i++) {
			Object obj = cache.get(i);
			if (!(obj instanceof IConfigurationElement))
				continue;

			IConfigurationElement element = (IConfigurationElement) obj;
			if (!TAG_PROVIDER.equals(element.getName()))
				continue;

			boolean doCreate = false;

			String attrValues = element.getAttribute(attrName);

			if (attrValues != null) {
				StringTokenizer tokenizer = new StringTokenizer(attrValues, ","); //$NON-NLS-1$
				while (tokenizer.hasMoreTokens()) {
					String type = tokenizer.nextToken();
					if (type.trim().equalsIgnoreCase(key.trim())) {
						doCreate = true;
						break;
					}
				}
			}

			if (doCreate) {
				IBreakpointProvider b = createBreakpointProvider(element);
				if (b != null) {
					bp[j] = b;
					j++;
				}
			}
		}

		IBreakpointProvider[] bp2 = new IBreakpointProvider[j];
		for (int i = 0; i < j; i++) {
			bp2[i] = bp[i];
		}

		return bp2;
	}

	/*
	 * Returns a matching array of extension points matching this key. Doesn't
	 * cause instantiation of providers. @return IBreakpointProvider[]
	 */
	protected IConfigurationElement[] findElements(String key) {
		initCache();

		if (cache == null || cache.size() == 0)
			return new IConfigurationElement[0];

		int num = cache.size();
		List elements = new ArrayList(1);
		for (int i = 0; i < num; i++) {
			Object obj = cache.get(i);
			if (!(obj instanceof IConfigurationElement))
				continue;

			IConfigurationElement element = (IConfigurationElement) obj;
			if (!TAG_PROVIDER.equals(element.getName()))
				continue;

			boolean add = false;
			String types = element.getAttribute(ATT_CONTENT_TYPES);
			String exts = element.getAttribute(ATT_EXTENSIONS);

			if (types == null && exts == null) {
				add = true;
			}

			if (!add && types != null) {
				StringTokenizer tokenizer = new StringTokenizer(types, ","); //$NON-NLS-1$
				while (tokenizer.hasMoreTokens()) {
					String type = tokenizer.nextToken();
					if (type.trim().equals(key.trim())) {
						add = true;
						break;
					}
				}
			}

			if (!add && exts != null) {
				StringTokenizer tokenizer = new StringTokenizer(exts, ","); //$NON-NLS-1$
				while (tokenizer.hasMoreTokens()) {
					String ext = tokenizer.nextToken();
					if (ext.trim().equals(key.trim())) {
						add = true;
						break;
					}
				}
			}

			if (add) {
				elements.add(element);
			}
		}
		return (IConfigurationElement[]) elements.toArray(new IConfigurationElement[0]);
	}

	/**
	 * Returns an array of breakpoint providers for a specified content type
	 * handler
	 * 
	 * @param handler
	 *            a content type handler
	 * @param ext
	 *            file extension
	 * @return IBreakpointProvider[]
	 */
	public IBreakpointProvider[] getBreakpointProviders(IEditorPart editorpart, String contentType, String ext) {
		initCache();

		// Get breakpoint providers for this content type handler
		IBreakpointProvider[] ps1 = new IBreakpointProvider[0];
		if (contentType != null) {
			ps1 = (IBreakpointProvider[]) map.get(contentType);
			if (ps1 == null) {
				ps1 = createBreakpointProviders(ATT_CONTENT_TYPES, contentType);
				if (ps1 != null) {
					map.put(contentType, ps1);
				}
			}
		}

		// Get breakpoint providers for this extension
		IBreakpointProvider[] ps2 = new IBreakpointProvider[0];
		if (ext != null) {
			ps2 = (IBreakpointProvider[]) map.get(ext);
			if (ps2 == null) {
				ps2 = createBreakpointProviders(ATT_EXTENSIONS, ext);
				if (ps2 != null) {
					map.put(ext, ps2);
				}
			}
		}

		// create single hash set to remove duplication
		Set s = new HashSet();
		for (int i = 0; i < ps1.length; i++) {
			s.add(ps1[i]);
		}
		for (int i = 0; i < ps2.length; i++) {
			s.add(ps2[i]);
		}

		// create IBreakpointProvider[] to return
		IBreakpointProvider[] providers = new IBreakpointProvider[s.size()];
		Iterator itr = s.iterator();
		int i = 0;
		SourceEditingTextTools tools = null;
		if (editorpart != null && itr.hasNext())
			tools = (SourceEditingTextTools) editorpart.getAdapter(SourceEditingTextTools.class);
		while (itr.hasNext()) {
			providers[i] = (IBreakpointProvider) itr.next();
			providers[i].setSourceEditingTextTools(tools);
			i++;
		}
		return providers;
	}

	/**
	 * Returns corresponding resource from given parameters
	 * 
	 * @param input
	 * @param handler
	 * @param ext
	 * @return IResource
	 */
	public IResource getResource(IEditorInput input, String contentType, String ext) {
		IBreakpointProvider[] providers = getBreakpointProviders(null, contentType, ext);
		IResource res = null;
		for (int i = 0; i < providers.length; i++) {
			res = providers[i].getResource(input);
			if (res != null) {
				break;
			}
		}
		return res;
	}

	private void initCache() {
		if (cache == null) {
			readContributions(TAG_BREAKPOINT_CONTRIBUTION, PL_BREAKPOINT);
		}
	}

	/**
	 * Returns an array of breakpoint providers for a specified content type
	 * handler
	 * 
	 * @param handler
	 *            a content type handler
	 * @param ext
	 *            file extension
	 * @return boolean
	 */
	public boolean isAvailable(String contentType, String ext) {
		boolean available = findElements(ext).length > 0;
		if (!available && contentType != null)
			available = findElements(contentType).length > 0;
		return available;
	}

	/**
	 * Reads the contributions from the registry for the provided workbench
	 * part and the provided extension point ID.
	 * 
	 * @param tag
	 * @param extensionPoint
	 */
	protected void readContributions(String tag, String extensionPoint) {
		cache = null;
		targetContributionTag = tag;
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		readRegistry(registry, PLUGIN_ID, extensionPoint);
	}

	/*
	 * @see com.ibm.sed.edit.internal.extension.RegistryReader#readElement(org.eclipse.core.runtime.IConfigurationElement)
	 */
	protected boolean readElement(IConfigurationElement element) {
		String tag = element.getName();
		if (tag.equals(targetContributionTag)) {
			readElementChildren(element);
			return true;
		} else if (tag.equals(TAG_PROVIDER)) {
			if (cache == null)
				cache = new ArrayList();
			cache.add(element);
			return true; // just cache the element - don't go into it
		}
		return false;
	}
}
