/*******************************************************************************
 * 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.core.runtime.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();
	}
}
