/*******************************************************************************
 * Copyright (c) 2000, 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
 *******************************************************************************/
package org.eclipse.compare.examples.xml;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.ListenerList;

import org.eclipse.compare.CompareUI;
import org.eclipse.core.runtime.*;
import org.osgi.framework.BundleContext;

/**
 * This class is the plug-in runtime class for the 
 * <code>"org.eclipse.compare.xml"</code> plug-in.
 * </p>
 */
public final class XMLPlugin extends AbstractUIPlugin {
	
	public static final String PLUGIN_ID= "org.eclipse.compare.examples.xml"; //$NON-NLS-1$

	private static final String ID_MAPPING_EXTENSION_POINT= "idMapping"; //$NON-NLS-1$
	private static final String MAPPING_ELEMENT_NAME= "mapping"; //$NON-NLS-1$
	private static final String IDMAP_NAME_ATTRIBUTE= "name"; //$NON-NLS-1$
	private static final String EXTENSION_NAME_ATTRIBUTE= "extension"; //$NON-NLS-1$
	private static final String MAPPING_SIGNATURE_ATTRIBUTE= "signature"; //$NON-NLS-1$
	private static final String MAPPING_ID_ATTRIBUTE= "id"; //$NON-NLS-1$
	private static final String MAPPING_ID_SOURCE= "id-source"; //$NON-NLS-1$
	private static final String MAPPING_ID_SOURCE_BODY= "body"; //$NON-NLS-1$
	private static final String ORDERED_ELEMENT_NAME= "ordered"; //$NON-NLS-1$
	private static final String ORDERED_SIGNATURE_ATTRIBUTE= "signature"; //$NON-NLS-1$
	
	public static final String DEFAULT_PREFIX = "XML"; //$NON-NLS-1$
	public static final String IMAGE_TYPE_PREFIX = "xml_"; //$NON-NLS-1$
	public static final String IMAGE_TYPE_ORDERED_SUFFIX = "_ordered"; //$NON-NLS-1$
	public static final String IDMAP_PREFERENCE_NAME = "idmap"; //$NON-NLS-1$
	public static final String IDMAP_PREFIX = "idmap"; //$NON-NLS-1$
	public static final char IDMAP_SEPARATOR = '*';
	public static final char IDMAP_FIELDS_SEPARATOR = '!';
	
	public static final String ORDERED_PREFERENCE_NAME = "ordered"; //$NON-NLS-1$
	public static final char ORDERED_FIELDS_SEPARATOR = IDMAP_FIELDS_SEPARATOR;
	
	private static XMLPlugin fgXMLPlugin;
	private IPreferenceStore fPrefStore;
	
	private HashMap fIdMapsInternal;
	private HashMap fIdMaps;
	private HashMap fIdExtensionToName;
	private HashMap fOrderedElementsInternal;
	private HashMap fOrderedElements;
	
	private ListenerList fViewers= new ListenerList();


	/**
	 * Creates the <code>XMLPlugin</code> object and registers all
	 * structure creators, content merge viewers, and structure merge viewers
	 * contributed to this plug-in's extension points.
	 * <p>
	 * Note that instances of plug-in runtime classes are automatically created 
	 * by the platform in the course of plug-in activation.
	 */
	public XMLPlugin() {
		super();
		Assert.isTrue(fgXMLPlugin == null);
		fgXMLPlugin= this;
	}
	
	public void start(BundleContext context) throws Exception {
		super.start(context);
		
		CompareUI.removeAllStructureViewerAliases(DEFAULT_PREFIX);
		initPrefStore();
		CompareUI.registerImageDescriptor(IMAGE_TYPE_PREFIX + XMLStructureCreator.TYPE_ELEMENT, getImageDescriptor("obj16/element_obj.gif")); //$NON-NLS-1$
		CompareUI.registerImageDescriptor(IMAGE_TYPE_PREFIX + XMLStructureCreator.TYPE_ATTRIBUTE, getImageDescriptor("obj16/attribute_obj.gif")); //$NON-NLS-1$
		CompareUI.registerImageDescriptor(IMAGE_TYPE_PREFIX + XMLStructureCreator.TYPE_TEXT, getImageDescriptor("obj16/text_obj.gif")); //$NON-NLS-1$
		CompareUI.registerImageDescriptor(IMAGE_TYPE_PREFIX + XMLStructureCreator.TYPE_ELEMENT + IMAGE_TYPE_ORDERED_SUFFIX, getImageDescriptor("obj16/element_ordered_obj.gif")); //$NON-NLS-1$
		registerExtensions();
	}
		
	protected ImageDescriptor getImageDescriptor(String relativePath) {
		
		//URL installURL= getDescriptor().getInstallURL();
		
		URL installURL= fgXMLPlugin.getBundle().getEntry("/"); //$NON-NLS-1$
		if (installURL != null) {
			try {
				URL url= new URL(installURL, "icons/full/" + relativePath); //$NON-NLS-1$
				return ImageDescriptor.createFromURL(url);
			} catch (MalformedURLException e) {
				Assert.isTrue(false);
			}
		}
		return null;
	}

	/**
	 * Returns the singleton instance of this plug-in runtime class.
	 *
	 * @return the XMLPlugin instance
	 */
	public static XMLPlugin getDefault() {
		return fgXMLPlugin;
	}

	/**
	 * Reads the Preference Store associated with XMLPlugin and initializes ID Mappings.
	 */	
	public void initPrefStore() {
		fIdMaps = new HashMap();
		fIdExtensionToName= new HashMap();
		fPrefStore = getPreferenceStore();
		String IdMapPrefValue = fPrefStore.getString(IDMAP_PREFERENCE_NAME);
		int start = 0;
		int end = IdMapPrefValue.indexOf(IDMAP_SEPARATOR);
		while (end >= 0) {
			String CurrentIdMap = IdMapPrefValue.substring(start,end);
			int end_of_IdMapName = CurrentIdMap.indexOf(IDMAP_FIELDS_SEPARATOR);
			String IdMapName = CurrentIdMap.substring(0,end_of_IdMapName);
			int end_of_signature = CurrentIdMap.indexOf(IDMAP_FIELDS_SEPARATOR,end_of_IdMapName+1);
			String IdMapSignature = CurrentIdMap.substring(end_of_IdMapName+1,end_of_signature);
			int end_of_attribute= CurrentIdMap.indexOf(IDMAP_FIELDS_SEPARATOR,end_of_signature+1);
			String IdMapAttribute;
			if (end_of_attribute < 0) {//for backward compatibility
				IdMapAttribute = CurrentIdMap.substring(end_of_signature+1,CurrentIdMap.length());
			} else {//normal case
				IdMapAttribute = CurrentIdMap.substring(end_of_signature+1,end_of_attribute);
				String IdMapExtension= CurrentIdMap.substring(end_of_attribute+1,CurrentIdMap.length());
				//if extension already associated, do not associate with this idmap
				if (!IdMapExtension.equals("") && !fIdExtensionToName.containsKey(IdMapExtension)) { //$NON-NLS-1$
					fIdExtensionToName.put(IdMapExtension,IdMapName);
					CompareUI.addStructureViewerAlias(DEFAULT_PREFIX, IdMapExtension);
				}
			}
			
			if (fIdMaps.containsKey(IdMapName)) {
				HashMap Mappings = (HashMap) fIdMaps.get(IdMapName);
				Mappings.put(IdMapSignature,IdMapAttribute);
			} else {
				HashMap Mappings = new HashMap();
				Mappings.put(IdMapSignature,IdMapAttribute);
				fIdMaps.put(IdMapName,Mappings);
			}
			start = end+1;
			end = IdMapPrefValue.indexOf(IDMAP_SEPARATOR,end+1);
		}
		
		fOrderedElements= new HashMap();
		String OrderedPrefValue= fPrefStore.getString(ORDERED_PREFERENCE_NAME);
		StringTokenizer orderedTokens= new StringTokenizer(OrderedPrefValue, (new Character(ORDERED_FIELDS_SEPARATOR)).toString());
		while (orderedTokens.hasMoreTokens()) {
			String IdMapName= orderedTokens.nextToken();
			String signature= orderedTokens.nextToken();
			if (fOrderedElements.containsKey(IdMapName)) {
				ArrayList idmapAL= (ArrayList) fOrderedElements.get(IdMapName);
				idmapAL.add(signature);
			} else {
				ArrayList idmapAL= new ArrayList();
				idmapAL.add(signature);
				fOrderedElements.put(IdMapName, idmapAL);
			}
		}

	}
	
	/*
	 * Updates the user Id Mappings, the IdExtensionToName mappings and refreshes the preference store.
	 * @param IdMap the new Id Mappings
	 * @param IdExtensionToName the new IdExtensionToName mappings
	 * @param refresh whether all the open StructureViewers should be refreshed with the new IdMapping settings
	 */
	public void setIdMaps(HashMap IdMap, HashMap IdExtensionToName, HashMap OrderedElements, boolean refresh) {
		fIdMaps = IdMap;
		if (IdExtensionToName != null && !IdExtensionToName.equals(fIdExtensionToName)) {
			CompareUI.removeAllStructureViewerAliases(DEFAULT_PREFIX);
			fIdExtensionToName= IdExtensionToName;
			Set newkeySet= fIdExtensionToName.keySet();
			for (Iterator iter= newkeySet.iterator(); iter.hasNext(); ) {
				String extension= (String)iter.next();
				CompareUI.addStructureViewerAlias(DEFAULT_PREFIX, extension);
			}
		}
		StringBuffer IdMapPrefValue = new StringBuffer();
		Set idmapKeys = fIdMaps.keySet();
		for (Iterator iter_idmap = idmapKeys.iterator(); iter_idmap.hasNext(); ) {
			String IdMapName = (String) iter_idmap.next();
			HashMap idmapHM = (HashMap) fIdMaps.get(IdMapName);
			Set mappingKeys = idmapHM.keySet();
			String extension= ""; //$NON-NLS-1$
			if (fIdExtensionToName.containsValue(IdMapName)) {
				Set keySet= fIdExtensionToName.keySet();
				for (Iterator iter= keySet.iterator(); iter.hasNext(); ) {
					extension= (String)iter.next();
					if ( ((String)fIdExtensionToName.get(extension)).equals(IdMapName) )
						break;
				}
			}
			for (Iterator iter_mapping = mappingKeys.iterator(); iter_mapping.hasNext(); ) {
				String signature = (String) iter_mapping.next();
				IdMapPrefValue.append(IdMapName+IDMAP_FIELDS_SEPARATOR+signature+IDMAP_FIELDS_SEPARATOR+idmapHM.get(signature)+IDMAP_FIELDS_SEPARATOR+extension+IDMAP_SEPARATOR);
			}
		}
		fPrefStore.setValue(IDMAP_PREFERENCE_NAME,IdMapPrefValue.toString());
		//fPrefStore.setValue(IDMAP_PREFERENCE_NAME,"");
		
		//stores OrderedElements
		if (OrderedElements != null) {
			fOrderedElements= OrderedElements;
			StringBuffer OrderedPrefValue= new StringBuffer();
			Set orderedKeys= fOrderedElements.keySet();
			for (Iterator iter_ordered= orderedKeys.iterator(); iter_ordered.hasNext();) {
				String IdMapName= (String) iter_ordered.next();
				ArrayList idmapAL= (ArrayList) fOrderedElements.get(IdMapName);
				for (Iterator iter_idmapAL= idmapAL.iterator(); iter_idmapAL.hasNext();) {
					String signature= (String) iter_idmapAL.next();
					OrderedPrefValue.append(IdMapName+ORDERED_FIELDS_SEPARATOR+signature+ORDERED_FIELDS_SEPARATOR);
				}
			}
			fPrefStore.setValue(ORDERED_PREFERENCE_NAME,OrderedPrefValue.toString());
			//fPrefStore.setValue(ORDERED_PREFERENCE_NAME,"");
		}

		if (refresh) {
			Object[] viewers = fViewers.getListeners();
			for (int i = 0; i < viewers.length; ++i) {
				XMLStructureViewer viewer = (XMLStructureViewer) viewers[i];
				viewer.updateIdMaps();
				viewer.contentChanged();
			}
		}
	}
	
	public HashMap getIdMaps() {
		return fIdMaps;
	}
	
	public HashMap getIdMapsInternal() {
		return fIdMapsInternal;
	}
	
	public HashMap getIdExtensionToName() {
		return fIdExtensionToName;
	}

	public HashMap getOrderedElements() {
		return fOrderedElements;
	}

	public HashMap getOrderedElementsInternal() {
		return fOrderedElementsInternal;
	}

	/**
	 * Registers all internal Id Mapping schemes
	 * that are found in plugin.xml files.
	 */
	private void registerExtensions() {
		IExtensionRegistry registry= Platform.getExtensionRegistry();
		
		// collect all Id Mappings
		IConfigurationElement[] idmaps= registry.getConfigurationElementsFor(PLUGIN_ID, ID_MAPPING_EXTENSION_POINT);
		fIdMapsInternal = new HashMap();
		fOrderedElementsInternal= new HashMap();
		for (int i_idmap= 0; i_idmap < idmaps.length; i_idmap++) {
			final IConfigurationElement idmap= idmaps[i_idmap];
			//handle IDMAP_NAME_ATTRIBUTE
			String idmap_name= idmap.getAttribute(IDMAP_NAME_ATTRIBUTE);
			//ignores idmap if its name equals the reserved name for unordered matching or the the name for ordered matching
			if ( !idmap_name.equals(XMLStructureCreator.USE_UNORDERED) && !idmap_name.equals(XMLStructureCreator.USE_ORDERED) ) {
				//handle mappings
				HashMap idmapHM = new HashMap();
				fIdMapsInternal.put(idmap_name, idmapHM);
				IConfigurationElement[] mappings = idmap.getChildren(MAPPING_ELEMENT_NAME);
				for (int i_mapping= 0; i_mapping < mappings.length; i_mapping++) {
					IConfigurationElement mapping = mappings[i_mapping];
					//add SIGN_SEPARATOR at the end because not contained in signatures of plugin.xml
					//also add prefix at beginning
					String signature= mapping.getAttribute(MAPPING_SIGNATURE_ATTRIBUTE);
					String attribute= mapping.getAttribute(MAPPING_ID_ATTRIBUTE);
					String idsource= mapping.getAttribute(MAPPING_ID_SOURCE);
					String bodyid= ""; //$NON-NLS-1$
					if (signature != null && !signature.equals("") //$NON-NLS-1$
						&& attribute != null && !attribute.equals("")) { //$NON-NLS-1$
						if (idsource != null && idsource.equals(MAPPING_ID_SOURCE_BODY))
							bodyid= (new Character(XMLStructureCreator.ID_TYPE_BODY)).toString();
						idmapHM.put(XMLStructureCreator.ROOT_ID	+ XMLStructureCreator.SIGN_SEPARATOR
								+ signature	+ XMLStructureCreator.SIGN_SEPARATOR, bodyid + attribute);
					}
				}
				//handles ordered entries
				IConfigurationElement[] orderedEntries= idmap.getChildren(ORDERED_ELEMENT_NAME);
				if (orderedEntries.length > 0) {
					ArrayList orderedAL= new ArrayList();
					for (int i_ordered= 0; i_ordered < orderedEntries.length; i_ordered++) {
						IConfigurationElement ordered= orderedEntries[i_ordered];
						//add SIGN_SEPARATOR at the end because not contained in signatures of plugin.xml
						//also add prefix at beginning
						String signature= ordered.getAttribute(ORDERED_SIGNATURE_ATTRIBUTE);
						if (signature != null && !signature.equals("")) //$NON-NLS-1$
							orderedAL.add(XMLStructureCreator.ROOT_ID + XMLStructureCreator.SIGN_SEPARATOR + signature + XMLStructureCreator.SIGN_SEPARATOR);
					}
					if (orderedAL.size() > 0)
						fOrderedElementsInternal.put(idmap_name, orderedAL);
				}
				//handle EXTENSION_NAME_ATTRIBUTE
				String ext_name= idmap.getAttribute(EXTENSION_NAME_ATTRIBUTE);
				if (ext_name != null && !fIdExtensionToName.containsKey(ext_name)) {
					ext_name= ext_name.toLowerCase();
					fIdExtensionToName.put(ext_name,idmap_name);
					CompareUI.addStructureViewerAlias(DEFAULT_PREFIX, ext_name);
				}				
			}
		}
	}

	public ListenerList getViewers() {
		return fViewers;
	}

	public static Shell getActiveWorkbenchShell() {
		IWorkbenchWindow window= getActiveWorkbenchWindow();
		if (window != null)
			return window.getShell();
		return null;
	}
	
	public static IWorkbenchWindow getActiveWorkbenchWindow() {
		IWorkbenchWindow window= fgXMLPlugin.getWorkbench().getActiveWorkbenchWindow();
		if (window == null) {
			final WindowRef windowRef= new WindowRef();
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					setActiveWorkbenchWindow(windowRef);
				}
			});
			return windowRef.window;
		}
		return window;
	}

	private static class WindowRef {
		public IWorkbenchWindow window;
	}

	private static void setActiveWorkbenchWindow(WindowRef windowRef) {
		windowRef.window= null;
		Display display= Display.getCurrent();
		if (display == null)
			return;
		Control shell= display.getActiveShell();
		while (shell != null) {
			Object data= shell.getData();
			if (data instanceof IWorkbenchWindow) {
				windowRef.window= (IWorkbenchWindow)data;
				return;
			}
			shell= shell.getParent();
		}
		Shell shells[]= display.getShells();
		for (int i= 0; i < shells.length; i++) {
			Object data= shells[i].getData();
			if (data instanceof IWorkbenchWindow) {
				windowRef.window= (IWorkbenchWindow)data;
				return;
			}
		}
	}	
	
	public static void log(Throwable e) {
		log(new Status(IStatus.ERROR, getPluginId(), IStatus.ERROR, "Internal Error", e)); //$NON-NLS-1$
	}
	
	public static void log(IStatus status) {
		getDefault().getLog().log(status);
	}
	
	public static String getPluginId() {
		return getDefault().getBundle().getSymbolicName();
	}
}
