/*******************************************************************************
 * Copyright (c) 2006, 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
 *******************************************************************************/
package org.eclipse.help.internal.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

/*
 * Provides an algorithm for determining a recommended sequence of items that
 * satisfies a primary sequence and as many secondary sequences as possible.
 *
 * For example, this is used to determine the display order of books on the tocs
 * based on the active product's preferred order as well as all other products'
 * preferred orders.
 */
public class SequenceResolver<T> {

	private List<T> primaryList;
	private List<T>[] secondaryLists;
	private ListIterator<T> primaryIter;
	private ListIterator<T>[] secondaryIters;
	private Set<T> processedItems;

	/*
	 * Merges the given primary and secondary orderings such that all ordering
	 * conditions from the primary are satisfied, and as many secondary ordering
	 * conditions as reasonably possible are also satisfied. An ordering condition
	 * is a pair of adjacent items in any ordering.
	 *
	 * For example:
	 *
	 *    primary =             {b, d, f}
	 *    secondary[0] =        {c, d, e}
	 *    secondary[1] =        {a, b, c}
	 *    -------------------------------
	 *    result =     {a, b, c, d, e, f}
	 *
	 * The algorithm works in iterations, where at each iteration we determine
	 * the next element in the recommended sequence. We maintain a pointer for
	 * each ordering to keep track of what we've already ordered.
	 *
	 * To determine the next item, we locate the current element in each ordering.
	 * These are the candidates for the next item as the next item can only be
	 * one of these.
	 *
	 * The top candidates are selected from the list of candidates, where a top
	 * candidate is one that has the lowest rank (there can be many). Rank is
	 * determined by how many other candidates appear before that candidate
	 * item in all the orderings. That is, we find out how many items
	 * the orderings list before each candidate.
	 *
	 * If a candidate has no other candidates listed before it, it will be
	 * the next item. If there are many, the first one is selected. If one of
	 * the top candidates is from the primary ordering (can only be one), it is
	 * automatically selected.
	 *
	 * Using the top rank ensures that if there are conflicts, and that
	 * as many orderings as possible are satisfied. For example, if most orderings
	 * want x before y, but a few want the opposite, x will be placed before y.
	 */
	public List<T> getSequence(List<T> primary, List<T>[] secondary) {
		primaryList = primary;
		secondaryLists = secondary;
		prepareDataStructures();
		List<T> order = new ArrayList<>();
		T item;
		while ((item = getNextItem()) != null) {
			processedItems.add(item);
			advanceIterator(primaryIter);
			for (int i=0;i<secondaryIters.length;++i) {
				advanceIterator(secondaryIters[i]);
			}
			order.add(item);
		}
		return order;
	}

	/*
	 * Create the data structures necessary for later operations.
	 */
	@SuppressWarnings("unchecked")
	private void prepareDataStructures() {
		primaryIter = primaryList.listIterator();
		secondaryIters = new ListIterator[secondaryLists.length];
		for (int i=0;i<secondaryLists.length;++i) {
			secondaryIters[i] = secondaryLists[i].listIterator();
		}
		processedItems = new HashSet<>();
	}

	/*
	 * Determine the next item in the sequence based on the top
	 * candidate items.
	 */
	private T getNextItem() {
		Candidate<T>[] candidates = getTopCandidates();
		switch(candidates.length) {
		case 0:
			return null;
		case 1:
			return candidates[0].item;
		default:
			for (int i=0;i<candidates.length;++i) {
				if (candidates[i].isPrimary) {
					return candidates[i].item;
				}
			}
			return candidates[0].item;
		}
	}

	/*
	 * Retrieves the top candidates from all the available next item candidates.
	 * These are the candidates that have the lowest rank
	 */
	private Candidate<T>[] getTopCandidates() {
		Candidate<T>[] candidates = getEligibleCandidates();
		rankCandidates(candidates);
		if (candidates.length > 0) {
			int topRank = candidates[0].rank;
			for (int i=1;i<candidates.length;++i) {
				if (candidates[i].rank < topRank) {
					topRank = candidates[i].rank;
				}
			}
			List<Candidate<T>> topCandidates = new ArrayList<>();
			for (int i=0;i<candidates.length;++i) {
				if (candidates[i].rank == topRank) {
					topCandidates.add(candidates[i]);
				}
			}
			return toCandidatesArray(topCandidates);
		}
		return candidates;
	}

	/*
	 * Returns all eligible candidates. A candidate is eligible if it does not
	 * conflict with the primary candidate. That is, if the primary candidate's list
	 * has that candidate after the primary candidate, it is contradicting the primary
	 * sequence and is not eligible.
	 */
	private Candidate<T>[] getEligibleCandidates() {
		Candidate<T>[] allCandidates = getAllCandidates();
		Candidate<T> primary = null;
		for (int i=0;i<allCandidates.length;++i) {
			if (allCandidates[i].isPrimary) {
				primary = allCandidates[i];
				break;
			}
		}
		// if we have no primary candidate then they're all eligible
		if (primary != null) {
			List<Candidate<T>> eligibleCandidates = new ArrayList<>(allCandidates.length);
			// primary candidate is always eligible
			eligibleCandidates.add(primary);
			Set<T> primarySet = Collections.singleton(primary.item);
			for (int i=0;i<allCandidates.length;++i) {
				Candidate<T> c = allCandidates[i];
				if (c != primary) {
					// does it contradict the primary sequence? if not, it is eligible
					if (countPrecedingItems(c.item, primary.src, primarySet) == 0) {
						eligibleCandidates.add(c);
					}
				}
			}
			return toCandidatesArray(eligibleCandidates);
		}
		return allCandidates;
	}

	/*
	 * Retrieve all the candidates for the next item in sequence, with
	 * no duplicates.
	 */
	private Candidate<T>[] getAllCandidates() {
		List<Candidate<T>> candidates = new ArrayList<>();
		T item = getNextItem(primaryIter);
		if (item != null) {
			Candidate<T> c = new Candidate<>();
			c.item = item;
			c.isPrimary = true;
			c.src = primaryList;
			candidates.add(c);
		}
		for (int i=0;i<secondaryIters.length;++i) {
			item = getNextItem(secondaryIters[i]);
			if (item != null) {
				Candidate<T> c = new Candidate<>();
				c.item = item;
				c.isPrimary = false;
				c.src = secondaryLists[i];
				if (!candidates.contains(c)) {
					candidates.add(c);
				}
			}
		}
		return toCandidatesArray(candidates);
	}

	/** Helper function as we cannot create arrays of parameterized types */
	@SuppressWarnings("unchecked")
	private Candidate<T>[] toCandidatesArray(List<Candidate<T>> candidates) {
		return candidates.toArray(new Candidate[candidates.size()]);
	}

	/*
	 * Assign a rank to each of the given candidates. Rank is determined by
	 * how many preceding candidates appear before that candidate in the orderings.
	 * This essentially means how far back this item should be in the final
	 * sequence.
	 */
	private void rankCandidates(Candidate<T>[] candidates) {
		// for quick lookup
		Set<T> candidateItems = new HashSet<>();
		for (int i=0;i<candidates.length;++i) {
			candidateItems.add(candidates[i].item);
		}
		for (int i=0;i<candidates.length;++i) {
			Candidate<T> c = candidates[i];
			for (int j=0;j<candidates.length;++j) {
				c.rank += countPrecedingItems(c.item, candidates[j].src, candidateItems);
			}
		}
	}

	/*
	 * Counts the number of elements from the given set that come before
	 * the given item in the given list.
	 */
	private int countPrecedingItems(Object item, List<?> list, Set<?> set) {
		int count = 0;
		Iterator<?> iter = list.iterator();
		while (iter.hasNext()) {
			Object next = iter.next();
			if (next.equals(item)) {
				return count;
			}
			if (set.contains(next)) {
				++count;
			}
		}
		return 0;
	}

	/*
	 * Returns the next item available to this iterator, without moving it
	 * forward.
	 */
	private T getNextItem(ListIterator<T> iter) {
		if (iter.hasNext()) {
			T next = iter.next();
			iter.previous();
			return next;
		}
		return null;
	}

	/*
	 * Advances the given iterator to the next item in its
	 * sequence that we haven't yet processed.
	 */
	private void advanceIterator(ListIterator<T> iter) {
		while (iter.hasNext()) {
			T item = iter.next();
			if (!processedItems.contains(item)) {
				iter.previous();
				break;
			}
		}
	}

	/*
	 * A candidate item; one that could potentially be the next one in the final
	 * sequence.
	 */
	private static class Candidate<T> {
		public T item;
		public boolean isPrimary;
		public int rank;
		public List<?> src;

		@Override
		public boolean equals(Object obj) {
			return item.equals(obj);
		}

		@Override
		public int hashCode() {
			return item.hashCode();
		}
	}
}
