/*******************************************************************************
 * Copyright (c) 2000, 2016 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
 *     James Blackburn - fix for Bug 230842
 *******************************************************************************/
package org.eclipse.help.internal.toc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
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.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.help.AbstractTocProvider;
import org.eclipse.help.IToc;
import org.eclipse.help.ITocContribution;
import org.eclipse.help.ITopic;
import org.eclipse.help.internal.HelpData;
import org.eclipse.help.internal.HelpPlugin;
import org.eclipse.help.internal.Topic;
import org.eclipse.help.internal.UAElement;
import org.eclipse.help.internal.UAElementFactory;

/*
 * Manages toc contributions (TocContribution) supplied by the various toc
 * providers (AbstractTocProvider).
 */
public class TocManager {

	private static final String EXTENSION_POINT_ID_TOC = HelpPlugin.PLUGIN_ID + ".toc"; //$NON-NLS-1$
	private static final String ELEMENT_NAME_TOC_PROVIDER = "tocProvider"; //$NON-NLS-1$
	private static final String ATTRIBUTE_NAME_CLASS = "class"; //$NON-NLS-1$

	private AbstractTocProvider[] tocProviders;
	// There are two sets of TOC contributions, one is used for Toc Assembly and is modified from the original
	// The other is used by the TocServlet and is unprocessed, i.e. anchors are not replaced with the contributions
	private Map<String, TocContribution[]> tocContributionsByLocale = new HashMap<>();
	private Map<String, TocContribution[]> tocContributionsForTocByLocale = new HashMap<>();
	private Map<String, Toc[]> tocsByLocale = new HashMap<>();
	private Map<String, Toc> tocsById = new HashMap<>();
	private Map<String, Toc> tocsByTopic;

	/*
	 * Returns all toc entries (complete books) for the given locale.
	 */
	public synchronized Toc[] getTocs(String locale) {
		Toc[] tocs = tocsByLocale.get(locale);
		if (tocs == null) {
			long start = System.currentTimeMillis();
			if (HelpPlugin.DEBUG_TOC) {
			    System.out.println("Start to build toc for locale " + locale); //$NON-NLS-1$
			}
			Set<String> tocsToFilter = getIgnoredTocContributions();
			TocContribution[] raw = getRootTocContributions(locale, tocsToFilter);
			TocContribution[] filtered = filterTocContributions(raw, tocsToFilter);
			ITocContribution[] ordered = new TocSorter().orderTocContributions(filtered);
			List<Toc> orderedTocs = new ArrayList<>(ordered.length);
			for (int i=0;i<ordered.length;++i) {
				try {
					Toc toc = (Toc)ordered[i].getToc();
					orderedTocs.add(toc);
					tocsById.put(ordered[i].getId(), toc);
				}
				catch (Throwable t) {
					// log and skip
					String msg = "Error getting " + Toc.class.getName() + " from " + ITocContribution.class.getName() + ": " + ordered[i]; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					HelpPlugin.logError(msg, t);
				}
			}
			tocs = orderedTocs.toArray(new Toc[orderedTocs.size()]);
			TopicSorter topicSorter = new TopicSorter();
			for (int i = 0; i < tocs.length; i++) {
				topicSorter.sortChildren(tocs[i]);
			}
			tocsByLocale.put(locale, tocs);
			long stop = System.currentTimeMillis();
			if (HelpPlugin.DEBUG_TOC) {
			    System.out.println("Milliseconds to update toc for locale " + locale +  " = " + (stop - start)); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		return tocs;
	}

	/*
	 * Returns the toc whose toc contribution has the given id, for the
	 * given locale.
	 */
	public synchronized Toc getToc(String id, String locale) {
		getTocs(locale);
		return tocsById.get(id);
	}

	public synchronized Toc getOwningToc(String href) {
		if (tocsByTopic == null) {
			tocsByTopic = new HashMap<>();
			Toc[] tocs = HelpPlugin.getTocManager().getTocs(Platform.getNL());
			for (int i=0;i<tocs.length;++i) {
				ITocContribution contribution = tocs[i].getTocContribution();
				String[] extraDocuments = contribution.getExtraDocuments();
				for (int j=0;j<extraDocuments.length;++j) {
					tocsByTopic.put(extraDocuments[j], tocs[i]);
				}
			}
		}
		return tocsByTopic.get(href);
	}

	public synchronized ITopic getTopic(String href, String locale) {
		Toc[] tocs = HelpPlugin.getTocManager().getTocs(locale);
		for (int i=0;i<tocs.length;++i) {
			ITopic topic = tocs[i].getTopic(href);
			if (topic != null) {
				return topic;
			}
		}
		int index = href.indexOf('#');
		if (index != -1) {
			return getTopic(href.substring(0, index), locale);
		}
		return null;
	}

	public synchronized int[] getTopicPath(String href, String locale) {
		ITopic topic = getTopic(href, locale);
		try {
			if (topic != null && topic instanceof UAElement) {
				List<Integer> path = new ArrayList<>();
				UAElement element = (UAElement) topic;
				while (!(element instanceof Toc)) {
					UAElement parent = element.getParentElement();
					path.add(new Integer(indexOf(parent, (Topic)element)));
					element = parent;
				}
				Toc[] tocs = getTocs(locale);
				for (int i=0;i<tocs.length;++i) {
					if (tocs[i] == element) {
						path.add(new Integer(i));
						int[] array = new int[path.size()];
						for (int j=0;j<array.length;++j) {
							array[j] = path.get(array.length - 1 - j).intValue();
						}
						return array;
					}
				}
			}
		} catch (Exception e) {
			return null;
		}
		// no path; not in toc
		return null;
	}

	/*
	 * Returns the zero-based index at which the child topic is located under
	 * the parent topic/toc.
	 */
	private int indexOf(UAElement parent, Topic child) {
		ITopic[] children;
		if (parent instanceof Topic) {
			children = ((Topic)parent).getSubtopics();
		}
		else if (parent instanceof Toc) {
			children = ((Toc)parent).getTopics();
		}
		else {
			return -1;
		}
		for (int i=0;i<children.length;++i) {
			if (children[i] == child) {
				return i;
			}
		}
		return -1;
	}

	/*
	 * Returns all toc contributions for the given locale, from all toc
	 * providers.
	 */
	public TocContribution[] getTocContributions(String locale) {
		return getAndCacheTocContributions(locale, tocContributionsByLocale);
	}

	private TocContribution[] getTocContributionsForToc(String locale) {
		return getAndCacheTocContributions(locale, tocContributionsForTocByLocale);
	}

	private synchronized TocContribution[] getAndCacheTocContributions(String locale,
			Map<String, TocContribution[]> contributionsByLocale) {
		TocContribution[] cached = contributionsByLocale.get(locale);
		if (cached == null) {
			HashMap<String, TocContribution> contributions = new HashMap<>();
			AbstractTocProvider[] providers = getTocProviders();
			for (int i=0;i<providers.length;++i) {
				ITocContribution[] contrib;
				try {
					contrib = providers[i].getTocContributions(locale);
					for (int j=0;j<contrib.length;++j) {
						TocContribution contribution = new TocContribution();
						contribution.setCategoryId(contrib[j].getCategoryId());
						contribution.setContributorId(contrib[j].getContributorId());
						contribution.setExtraDocuments(contrib[j].getExtraDocuments());
						contribution.setId(contrib[j].getId());
						contribution.setLocale(contrib[j].getLocale());
						contribution.setPrimary(contrib[j].isPrimary());
						IToc toc = contrib[j].getToc();
						Toc t = toc instanceof Toc ? (Toc)toc : (Toc)UAElementFactory.newElement(toc);
						t.setLinkTo(contrib[j].getLinkTo());
						contribution.setToc(t);
						if(!contributions.containsKey(contrib[j].getId()))
							contributions.put(contrib[j].getId(), contribution);
					}
				}
				catch (Throwable t) {
					// log, and skip the offending provider
					String msg = "Error getting help table of contents data from provider: " + providers[i].getClass().getName() + " (skipping provider)"; //$NON-NLS-1$ //$NON-NLS-2$
					HelpPlugin.logError(msg, t);
					continue;
				}

			}
			cached = contributions.values().toArray(new TocContribution[contributions.size()]);
			contributionsByLocale.put(locale, cached);
		}
		return cached;
	}

	/*
	 * Clears all cached contributions, forcing the manager to query the
	 * providers again next time a request is made.
	 */
	public void clearCache() {
		tocContributionsByLocale.clear();
		tocContributionsForTocByLocale.clear();
		tocsByLocale.clear();
		tocsById.clear();
		tocsByTopic = null;
		tocProviders=null;
	}

	/*
	 * Internal hook for unit testing.
	 */
	public AbstractTocProvider[] getTocProviders() {
		if (tocProviders == null) {
			List<AbstractTocProvider> providers = new ArrayList<>();
			IExtensionRegistry registry = Platform.getExtensionRegistry();
			IConfigurationElement[] elements = registry.getConfigurationElementsFor(EXTENSION_POINT_ID_TOC);
			for (int i=0;i<elements.length;++i) {
				IConfigurationElement elem = elements[i];
				if (elem.getName().equals(ELEMENT_NAME_TOC_PROVIDER)) {
					try {
						AbstractTocProvider provider = (AbstractTocProvider)elem.createExecutableExtension(ATTRIBUTE_NAME_CLASS);
						providers.add(provider);
					}
					catch (CoreException e) {
						// log and skip
						String msg = "Error instantiating help table of contents provider class \"" + elem.getAttribute(ATTRIBUTE_NAME_CLASS) + '"'; //$NON-NLS-1$
						HelpPlugin.logError(msg, e);
					}
				}
			}
			Collections.sort(providers, new TocProviderComparator());
			tocProviders = providers.toArray(new AbstractTocProvider[providers.size()]);
		}
		return tocProviders;
	}

	/*
	 * Internal hook for unit testing.
	 */
	public void setTocProviders(AbstractTocProvider[] tocProviders) {
		this.tocProviders = tocProviders;
	}

	/*
	 * Filters the given contributions according to product preferences. If
	 * either the contribution's id or its category's id is listed in the
	 * ignoredTocs, filter the contribution.
	 */
	private TocContribution[] filterTocContributions(TocContribution[] unfiltered, Set<String> tocsToFilter) {
		List<TocContribution> filtered = new ArrayList<>();
		for (int i=0;i<unfiltered.length;++i) {
			if (!tocsToFilter.contains(unfiltered[i].getId()) &&
					!tocsToFilter.contains(unfiltered[i].getCategoryId())) {
				filtered.add(unfiltered[i]);
			}
		}
		return filtered.toArray(new TocContribution[filtered.size()]);
	}

	private TocContribution[] getRootTocContributions(String locale, Set<String> tocsToFilter) {
		TocContribution[] contributions = getTocContributionsForToc(locale);
		List<TocContribution> unassembled = new ArrayList<>(Arrays.asList(contributions));
		TocAssembler assembler = new TocAssembler(tocsToFilter);
		List<TocContribution> assembled = assembler.assemble(unassembled);
		return assembled.toArray(new TocContribution[assembled.size()]);
	}

	private Set<String> getIgnoredTocContributions() {
		HelpData helpData = HelpData.getProductHelpData();
		if (helpData != null) {
			return helpData.getHiddenTocs();
		}
		else {
			HashSet<String> ignored = new HashSet<>();
			String preferredTocs = Platform.getPreferencesService().getString(HelpPlugin.PLUGIN_ID, HelpPlugin.IGNORED_TOCS_KEY, "", null); //$NON-NLS-1$
			if (preferredTocs.length() > 0) {
				StringTokenizer suggestdOrderedInfosets = new StringTokenizer(preferredTocs, " ;,"); //$NON-NLS-1$
				while (suggestdOrderedInfosets.hasMoreTokens()) {
					ignored.add(suggestdOrderedInfosets.nextToken());
				}
			}
			return ignored;
		}
	}

	/*
	 * Returns whether or not the toc for the given locale has been completely
	 * loaded yet or not.
	 */
	public boolean isTocLoaded(String locale) {
		return tocsByLocale.get(locale) != null;
	}

}
