/*******************************************************************************
 * Copyright (c) 2002, 2017 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.ui.internal.cheatsheets.registry;

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

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionDelta;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
import org.eclipse.ui.internal.cheatsheets.Messages;

import com.ibm.icu.text.Collator;

/**
 *  Instances access the registry that is provided at creation time
 *  in order to determine the contained CheatSheet Contents
 */
public class CheatSheetRegistryReader extends RegistryReader implements IRegistryChangeListener {

	private class CategoryNode {
		private Category category;
		private String path;
		public CategoryNode(Category cat) {
			category = cat;
			path = ICheatSheetResource.EMPTY_STRING;
			String[] categoryPath = category.getParentPath();
			if (categoryPath != null) {
				for (int nX = 0; nX < categoryPath.length; nX++) {
					path += categoryPath[nX] + '/';
				}
			}
			path += cat.getId();
		}
		public Category getCategory() {
			return category;
		}
		public String getPath() {
			return path;
		}
	}

	/**
     * Represents a taskEditor entry in the registry
	 */
	public class TaskEditorNode {
		private String className;
		private String iconPath;
		private String id;
		private String pluginId;
		public void setClassName(String className) {
			this.className = className;
		}
		public String getClassName() {
			return className;
		}
		public void setIconPath(String iconPath) {
			this.iconPath = iconPath;
		}
		public String getIconPath() {
			return iconPath;
		}
		public void setId(String id) {
			this.id = id;
		}
		public String getId() {
			return id;
		}
		public void setPluginId(String pluginId) {
			this.pluginId = pluginId;
		}
		public String getPluginId() {
			return pluginId;
		}
	}

	/**
     * Represents a taskExplorer entry in the registry
	 */
	public class TaskExplorerNode {
		private String className;
		private String iconPath;
		private String name;
		private String id;
		private String pluginId;
		public void setClassName(String className) {
			this.className = className;
		}
		public String getClassName() {
			return className;
		}
		public void setIconPath(String iconPath) {
			this.iconPath = iconPath;
		}
		public String getIconPath() {
			return iconPath;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		public void setId(String id) {
			this.id = id;
		}
		public String getId() {
			return id;
		}
		public void setPluginId(String pluginId) {
			this.pluginId = pluginId;
		}
		public String getPluginId() {
			return pluginId;
		}
	}

	// constants
	private final static String ATT_CATEGORY = "category"; //$NON-NLS-1$
	public final static String ATT_CONTENTFILE = "contentFile"; //$NON-NLS-1$
	protected final static String ATT_ICON = "icon"; //$NON-NLS-1$
	protected final static String ATT_ID = "id"; //$NON-NLS-1$
	protected final static String ATT_LISTENERCLASS = "listener"; //$NON-NLS-1$
	protected final static String ATT_NAME = "name"; //$NON-NLS-1$
	protected final static String ATT_CLASS = "class"; //$NON-NLS-1$
	private final static String ATT_COMPOSITE = "composite"; //$NON-NLS-1$
	private final static String CATEGORY_SEPARATOR = "/"; //$NON-NLS-1$
	private final static String ATT_ITEM_ATTRIBUTE = "itemAttribute"; //$NON-NLS-1$
	private static CheatSheetRegistryReader instance;
	private final static String TAG_CATEGORY = "category"; //$NON-NLS-1$
	public final static String TAG_CHEATSHEET = "cheatsheet"; //$NON-NLS-1$
	protected final static String TAG_ITEM_EXTENSION = "itemExtension"; //$NON-NLS-1$
	protected final static String TAG_TASK_EDITOR = "taskEditor"; //$NON-NLS-1$
	protected final static String TAG_TASK_EXPLORER = "taskExplorer"; //$NON-NLS-1$
	protected final static String trueString = "TRUE"; //$NON-NLS-1$
	private final static String UNCATEGORIZED_CHEATSHEET_CATEGORY = "org.eclipse.ui.Other"; //$NON-NLS-1$
	private final static String UNCATEGORIZED_CHEATSHEET_CATEGORY_LABEL = Messages.CHEAT_SHEET_OTHER_CATEGORY;
    public final static String CHEAT_SHEET_CONTENT = "cheatSheetContent"; //$NON-NLS-1$

    /**
	 * Returns a list of cheatsheets, project and not.
	 *
	 * The return value for this method is cached since computing its value
	 * requires non-trivial work.
	 */
	public static CheatSheetRegistryReader getInstance() {
		if (instance == null) {
			instance = new CheatSheetRegistryReader();
			IExtensionRegistry xregistry = Platform.getExtensionRegistry();
			xregistry.addRegistryChangeListener(instance, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID);
		}

		return instance;
	}

	protected ArrayList<CheatSheetItemExtensionElement> cheatsheetItemExtensions;
	protected CheatSheetCollectionElement cheatsheets;
	private ArrayList<Category> deferCategories = null;
	private ArrayList<CheatSheetElement> deferCheatSheets = null;
	private final String csItemExtension = "cheatSheetItemExtension"; //$NON-NLS-1$
	protected Map<String, TaskExplorerNode> taskExplorers = new HashMap<>();
	protected Map<String, TaskEditorNode> taskEditors = new HashMap<>();
	private Map nestedCategoryIds = new HashMap();

	/**
	 *	Create an instance of this class.
	 */
	private CheatSheetRegistryReader() {
	}

	/**
	 * Adds new cheatsheet to the provided collection. Override to
	 * provide more logic.
	 * <p>
	 * This implementation uses a defering strategy.  For more info see
	 * <code>readCheatSheets</code>.
	 * </p>
	 */
	protected void addNewElementToResult(CheatSheetElement element, IConfigurationElement config, CheatSheetCollectionElement cheatsheets2) {
		deferCheatSheet(element);
	}

	/**
	 * Returns a new CheatSheetElement configured according to the parameters
	 * contained in the passed Registry.
	 *
	 * May answer null if there was not enough information in the Extension to create
	 * an adequate cheatsheet
	 */
	protected CheatSheetElement createCheatSheetElement(IConfigurationElement element) {
		// CheatSheetElements must have a name attribute
		String nameString = element.getAttribute(ATT_NAME);
		if (nameString == null) {
			logMissingAttribute(element, ATT_NAME);
			return null;
		}
		CheatSheetElement result = new CheatSheetElement(nameString);
		if (initializeCheatSheet(result, element))
			return result; // ie.- initialization was successful

		return null;
	}

	/**
	 *	Create and answer a new CheatSheetCollectionElement, configured as a
	 *	child of <code>parent</code>
	 *
	 *	@return org.eclipse.ui.internal.model.CheatSheetCollectionElement
	 *	@param parent org.eclipse.ui.internal.model.CheatSheetCollectionElement
	 *	@param childName java.lang.String
	 */
	protected CheatSheetCollectionElement createCollectionElement(CheatSheetCollectionElement parent, String pluginId, String id, String label) {
		CheatSheetCollectionElement newElement = new CheatSheetCollectionElement(pluginId, id, label, parent);

		parent.add(newElement);
		return newElement;
	}

	/**
	 * Creates empty element collection. Overrider to fill
	 * initial elements, if needed.
	 */
	protected CheatSheetCollectionElement createEmptyCheatSheetCollection() {
		return new CheatSheetCollectionElement(null, "root", "root", null); //$NON-NLS-1$//$NON-NLS-2$
	}

	/**
	 * Stores a category element for deferred addition.
	 */
	private void deferCategory(IConfigurationElement config) {
		// Create category.
		Category category = null;
		try {
			category = new Category(config);
		} catch (CoreException e) {
			CheatSheetPlugin.getPlugin().getLog().log(e.getStatus());
			return;
		}

		// Defer for later processing.
		if (deferCategories == null)
			deferCategories = new ArrayList<>(20);
		deferCategories.add(category);
	}

	/**
	 * Stores a cheatsheet element for deferred addition.
	 */
	private void deferCheatSheet(CheatSheetElement element) {
		if (deferCheatSheets == null)
			deferCheatSheets = new ArrayList<>(50);
		deferCheatSheets.add(element);
	}

	/**
	 *	Returns the first cheatsheet
	 *  with a given id.
	 */
	public CheatSheetElement findCheatSheet(String id) {
		Object[] cheatsheetsList = getCheatSheets().getChildren();
		for (int nX = 0; nX < cheatsheetsList.length; nX++) {
			CheatSheetCollectionElement collection = (CheatSheetCollectionElement) cheatsheetsList[nX];
			CheatSheetElement element = collection.findCheatSheet(id, true);
			if (element != null)
				return element;
		}
		return null;
	}

	/**
	 *	Returns the first task editor
	 *  with a given id.
	 */
	public TaskEditorNode findTaskEditor(String id) {
		if (cheatsheets == null) {
		    readCheatSheets(); // Ensure that the registry has been read
		}
		return taskEditors.get(id);
	}

	/**
	 *	Returns the first task explorer
	 *  with a given id.
	 */
	public TaskExplorerNode findTaskExplorer(String id) {
		if (cheatsheets == null) {
		    readCheatSheets(); // Ensure that the registry has been read
		}
		return taskExplorers.get(id);
	}

	/**
	 * Get the list of explorer ids
	 * @return an iterator for the explorer ids
	 */
	public String[] getExplorerIds() {
		if (cheatsheets == null) {
		    readCheatSheets(); // Ensure that the registry has been read
		}
		Set<String> keys = taskExplorers.keySet();
		return keys.toArray(new String[keys.size()]);
	}

	/**
	 * Finishes the addition of categories.  The categories are sorted and
	 * added in a root to depth traversal.
	 */
	private void finishCategories() {
		// If no categories just return.
		if (deferCategories == null)
			return;

		// Sort categories by flattened name.
		CategoryNode[] flatArray = new CategoryNode[deferCategories.size()];
		for (int i = 0; i < deferCategories.size(); i++) {
			flatArray[i] = new CategoryNode(deferCategories.get(i));
		}
		Sorter sorter = new Sorter() {
			private Collator collator = Collator.getInstance();

			@Override
			public boolean compare(Object o1, Object o2) {
				String s1 = ((CategoryNode) o1).getPath();
				String s2 = ((CategoryNode) o2).getPath();
				return collator.compare(s2, s1) > 0;
			}
		};
		Object[] sortedCategories = sorter.sort(flatArray);

		// Add each category.
		for (int nX = 0; nX < sortedCategories.length; nX++) {
			Category cat = ((CategoryNode) sortedCategories[nX]).getCategory();
			finishCategory(cat);
		}

		// Cleanup.
		deferCategories = null;
	}

	/**
	 * Save new category definition.
	 */
	private void finishCategory(Category category) {
		CheatSheetCollectionElement currentResult = cheatsheets;

		String[] categoryPath = category.getParentPath();
		CheatSheetCollectionElement parent = currentResult; // ie.- root

		// Traverse down into parent category.
		if (categoryPath != null) {
			nestedCategoryIds.put(category.getId(), category);
			for (int i = 0; i < categoryPath.length; i++) {
				CheatSheetCollectionElement tempElement = getChildWithID(parent, categoryPath[i]);
				if (tempElement == null) {
					// The parent category is invalid.  By returning here the
					// category will be dropped and any cheatsheet within the category
					// will be added to the "Other" category.
					return;
				}
				parent = tempElement;
			}
		}

		// If another category already exists with the same id ignore this one.
		Object test = getChildWithID(parent, category.getId());
		if (test != null)
			return;

		if (parent != null) {
			CheatSheetCollectionElement collectionElement =
				createCollectionElement(parent, category.getPluginId(), category.getId(), category.getLabel());
			if (categoryPath != null) {
				nestedCategoryIds.put(category.getId(), collectionElement);
			}
		}
	}

	/**
	 *	Insert the passed cheatsheet element into the cheatsheet collection appropriately
	 *	based upon its defining extension's CATEGORY tag value
	 *
	 *	@param element CheatSheetElement
	 *	@param extension
	 *	@param currentResult CheatSheetCollectionElement
	 */
	private void finishCheatSheet(CheatSheetElement element, IConfigurationElement config, CheatSheetCollectionElement result) {
		CheatSheetCollectionElement currentResult = result;
		String category = getCategoryStringFor(config);
		StringTokenizer familyTokenizer = new StringTokenizer(category, CATEGORY_SEPARATOR);

		// use the period-separated sections of the current CheatSheet's category
		// to traverse through the NamedSolution "tree" that was previously created
		CheatSheetCollectionElement currentCollectionElement = currentResult; // ie.- root
		boolean moveToOther = false;

		while (familyTokenizer.hasMoreElements()) {
			CheatSheetCollectionElement tempCollectionElement = getChildWithID(currentCollectionElement, familyTokenizer.nextToken());

			if (tempCollectionElement == null) { // can't find the path; look for a simple path

				moveToOther = true;
				break;
			}
			currentCollectionElement = tempCollectionElement;
		}

		if (moveToOther) {
			if (nestedCategoryIds.containsKey(category)) {
				currentCollectionElement = (CheatSheetCollectionElement) nestedCategoryIds.get(category);
				currentCollectionElement.add(element);
			} else {
			    moveElementToUncategorizedCategory(currentResult, element);
			}
		} else {
			currentCollectionElement.add(element);
		}
	}

	/**
	 * Finishes the addition of cheatsheets.  The cheatsheets are processed and categorized.
	 */
	private void finishCheatSheets() {
		if (deferCheatSheets != null) {
			Iterator<CheatSheetElement> iter = deferCheatSheets.iterator();
			while (iter.hasNext()) {
				CheatSheetElement cheatsheet = iter.next();
				IConfigurationElement config = cheatsheet.getConfigurationElement();
				finishCheatSheet(cheatsheet, config, cheatsheets);
			}
			deferCheatSheets = null;
		}
		nestedCategoryIds = null;
	}

	/**
	 *	Return the appropriate category (tree location) for this CheatSheet.
	 *	If a category is not specified then return a default one.
	 */
	protected String getCategoryStringFor(IConfigurationElement config) {
		String result = config.getAttribute(ATT_CATEGORY);
		if (result == null)
			result = UNCATEGORIZED_CHEATSHEET_CATEGORY;

		return result;
	}

	/**
	 * Returns a list of cheatsheets, project and not.
	 *
	 * The return value for this method is cached since computing its value
	 * requires non-trivial work.
	 */
	public CheatSheetCollectionElement getCheatSheets() {
		if (cheatsheets == null)
			readCheatSheets();
		return cheatsheets;
	}

	/**
	 *	Go through the children of  the passed parent and answer the child
	 *	with the passed name.  If no such child is found then return null.
	 *
	 *	@return org.eclipse.ui.internal.model.CheatSheetCollectionElement
	 *	@param parent org.eclipse.ui.internal.model.CheatSheetCollectionElement
	 *	@param childName java.lang.String
	 */
	protected CheatSheetCollectionElement getChildWithID(CheatSheetCollectionElement parent, String id) {
		Object[] children = parent.getChildren();
		for (int i = 0; i < children.length; ++i) {
			CheatSheetCollectionElement currentChild = (CheatSheetCollectionElement) children[i];
			if (currentChild.getId().equals(id))
				return currentChild;
		}
		return null;
	}

	/**
	 *	Initialize the passed element's properties based on the contents of
	 *	the passed registry.  Answer a boolean indicating whether the element
	 *	was able to be adequately initialized.
	 *
	 *	@return boolean
	 *	@param element CheatSheetElement
	 *	@param extension Extension
	 */
	protected boolean initializeCheatSheet(CheatSheetElement element, IConfigurationElement config) {
		element.setID(config.getAttribute(ATT_ID));
		element.setDescription(getDescription(config));
		element.setConfigurationElement(config);
		element.setRegistered(true);

		String contentFile = config.getAttribute(ATT_CONTENTFILE);
		if (contentFile != null) {
			element.setContentFile(contentFile);
		}

		// ensure that a contentfile was specified
		if (element.getConfigurationElement() == null || element.getContentFile() == null) {
			logMissingAttribute(config, ATT_CONTENTFILE);
			return false;
		}

		String listenerClass = config.getAttribute(ATT_LISTENERCLASS);
		if (listenerClass != null) {
			element.setListenerClass(listenerClass);
		}
		String composite = config.getAttribute(ATT_COMPOSITE);
		if (composite != null) {
			element.setComposite(composite.equalsIgnoreCase(trueString));
		}
		return true;
	}

	/**
	 *	Moves given element to "Other" category, previously creating one if missing.
	 */
	protected void moveElementToUncategorizedCategory(CheatSheetCollectionElement root, CheatSheetElement element) {
		CheatSheetCollectionElement otherCategory = getChildWithID(root, UNCATEGORIZED_CHEATSHEET_CATEGORY);

		if (otherCategory == null)
			otherCategory = createCollectionElement(root, null, UNCATEGORIZED_CHEATSHEET_CATEGORY, UNCATEGORIZED_CHEATSHEET_CATEGORY_LABEL);

		otherCategory.add(element);
	}

	/**
	 * Removes the empty categories from a cheatsheet collection.
	 */
	private void pruneEmptyCategories(CheatSheetCollectionElement parent) {
		Object[] children = parent.getChildren();
		for (int nX = 0; nX < children.length; nX++) {
			CheatSheetCollectionElement child = (CheatSheetCollectionElement) children[nX];
			pruneEmptyCategories(child);
		}
	}

	/**
	 * Reads the cheatsheets in a registry.
	 * <p>
	 * This implementation uses a defering strategy.  All of the elements
	 * (categories, cheatsheets) are read.  The categories are created as the read occurs.
	 * The cheatsheets are just stored for later addition after the read completes.
	 * This ensures that cheatsheet categorization is performed after all categories
	 * have been read.
	 * </p>
	 */
	protected void readCheatSheets() {
		IExtensionRegistry xregistry = Platform.getExtensionRegistry();

		if (cheatsheets == null) {
			cheatsheets = createEmptyCheatSheetCollection();
			readRegistry(xregistry, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, CHEAT_SHEET_CONTENT);
		}

		finishCategories();
		finishCheatSheets();

		if (cheatsheets != null) {
			CheatSheetCollectionElement parent = cheatsheets;
			pruneEmptyCategories(parent);
		}
	}

	public ArrayList<CheatSheetItemExtensionElement> readItemExtensions() {
		if (cheatsheetItemExtensions == null) {
			cheatsheetItemExtensions = new ArrayList<>();

			IExtensionRegistry xregistry = Platform.getExtensionRegistry();
			//Now read the cheat sheet extensions.
			readRegistry(xregistry, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, csItemExtension);
		}

		return cheatsheetItemExtensions;
	}

	private void createItemExtensionElement(IConfigurationElement element) {
		String className = element.getAttribute(ATT_CLASS);
		String itemAttribute = element.getAttribute(ATT_ITEM_ATTRIBUTE);

		// ensure that a class was specified
		if (className == null) {
			logMissingAttribute(element, ATT_CLASS);
			return;
		}
		// ensure that a itemAttribute was specified
		if (itemAttribute == null) {
			logMissingAttribute(element, ATT_ITEM_ATTRIBUTE);
			return;
		}

		CheatSheetItemExtensionElement itemExtensionElement = new CheatSheetItemExtensionElement();
		itemExtensionElement.setClassName(className);
		itemExtensionElement.setItemAttribute(itemAttribute);
		itemExtensionElement.setConfigurationElement(element);

		cheatsheetItemExtensions.add(itemExtensionElement);
	}

	/*
	 * Get a required attribute. Log an error if it has no value.
	 */
	private String getAndCheckAttribute(IConfigurationElement element, String name) {
		String result = element.getAttribute(name);
		if (result == null) {
			logMissingAttribute(element, name);
		}
		return result;
	}

	private void createTaskExplorerElement(IConfigurationElement element) {
		String icon = element.getAttribute(ATT_ICON);
		String className = getAndCheckAttribute(element, ATT_CLASS);
		String name = getAndCheckAttribute(element, ATT_NAME);
		String id = getAndCheckAttribute(element, ATT_ID);
		String pluginId = element.getContributor().getName();
		if (id != null && className != null && name != null ) {
			TaskExplorerNode node = new TaskExplorerNode();
            node.setId(id);
			node.setIconPath(icon);
			node.setClassName(className);
			node.setName(name);
			node.setPluginId(pluginId);
			taskExplorers.put(id, node);
		}
	}

	private void createTaskEditorElement(IConfigurationElement element) {
		String icon = getAndCheckAttribute(element, ATT_ICON);
		String className = getAndCheckAttribute(element, ATT_CLASS);
		String id = getAndCheckAttribute(element, ATT_ID);
		String pluginId = element.getContributor().getName();
		if (id != null && className != null && icon != null ) {
			TaskEditorNode node = new TaskEditorNode();
            node.setId(id);
			node.setIconPath(icon);
			node.setClassName(className);
			node.setPluginId(pluginId);
			taskEditors.put(id, node);
		}
	}

	/**
	 * Implement this method to read element attributes.
	 */
	@Override
	protected boolean readElement(IConfigurationElement element) {
		if (element.getName().equals(TAG_CATEGORY)) {
			deferCategory(element);
			return true;
		} else if (element.getName().equals(TAG_ITEM_EXTENSION)) {
			createItemExtensionElement(element);
			return true;
		} else if (element.getName().equals(TAG_TASK_EDITOR)) {
			createTaskEditorElement(element);
			return true;
		} else if (element.getName().equals(TAG_TASK_EXPLORER)) {
			createTaskExplorerElement(element);
			return true;
		} else {
			if (!element.getName().equals(TAG_CHEATSHEET))
				return false;

			CheatSheetElement cheatsheet = createCheatSheetElement(element);
			if (cheatsheet != null)
				addNewElementToResult(cheatsheet, element, cheatsheets);
			return true;
		}
	}

	@Override
	public void registryChanged(IRegistryChangeEvent event) {
		IExtensionDelta[] cheatSheetDeltas = event.getExtensionDeltas(ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, CHEAT_SHEET_CONTENT);
		if (cheatSheetDeltas.length > 0) {
			// reset the list of cheat sheets, it will be build on demand
			cheatsheets = null;
		}

		IExtensionDelta[] itemExtensionDeltas = event.getExtensionDeltas(ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, csItemExtension);
		if (itemExtensionDeltas.length > 0) {
			// reset the list of cheat sheets item extensions, it will be build on demand
			cheatsheetItemExtensions = null;
		}
	}

	public void stop() {
		IExtensionRegistry xregistry = Platform.getExtensionRegistry();
		xregistry.removeRegistryChangeListener(instance);

		instance = null;
	}
}
