/*******************************************************************************
 * Copyright (c) 2007, 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
 *     Yaroslav Nikolaiko <nikolaiko.yaroslav@gmail.com> - [webapp][base] Bugs related to Search Scope for filtering content in The Eclipse platform's help infocenter - http://bugs.eclipse.org/441407
 *******************************************************************************/
package org.eclipse.help.internal.webapp.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.help.IIndex;
import org.eclipse.help.IIndexEntry;
import org.eclipse.help.IIndexEntry2;
import org.eclipse.help.IIndexSee;
import org.eclipse.help.IIndexSubpath;
import org.eclipse.help.ITopic;
import org.eclipse.help.base.AbstractHelpScope;
import org.eclipse.help.internal.HelpPlugin;
import org.eclipse.help.internal.base.scope.ScopeUtils;
import org.eclipse.help.internal.webapp.WebappResources;
import org.eclipse.help.internal.webapp.data.ActivitiesData;
import org.eclipse.help.internal.webapp.data.RequestScope;
import org.eclipse.help.internal.webapp.data.UrlUtil;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.Collator;

/*
 * Creates xml representing selected parts of the index
 * Parameter "start" represents the part of the index to start reading from
 * Parameter "size" indicates the number of entries to read, no size parameter
 * or a negative size parameter indicates that all entries which match the start
 * letters should be displayed.
 * Parameter "offset" represents the starting point relative to the start
 */
public class IndexFragmentServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static Map<String, String> locale2Response = new WeakHashMap<>();
	private String startParameter;
	private String sizeParameter;
	private String entryParameter;
	private String modeParameter;
	private String showAllParameter;
	private int size;
	private int entry;
	private static final String NEXT = "next"; //$NON-NLS-1$
	private static final String PREVIOUS = "previous"; //$NON-NLS-1$
	private static final String SIZE = "size"; //$NON-NLS-1$
	private static final String MODE = "mode"; //$NON-NLS-1$
	private static final String ENTRY = "entry"; //$NON-NLS-1$
	private static final String SHOW_ALL = "showAll"; //$NON-NLS-1$
	private Collator collator = Collator.getInstance();

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// set the character-set to UTF-8 before calling resp.getWriter()
		resp.setContentType("application/xml; charset=UTF-8"); //$NON-NLS-1$
		resp.getWriter().write(processRequest(req, resp));
	}

	protected String processRequest(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String locale = UrlUtil.getLocale(req, resp);
		startParameter = req.getParameter("start"); //$NON-NLS-1$
		if (startParameter != null) {
			startParameter = startParameter.toLowerCase();
		}

		size = 30;
		sizeParameter = req.getParameter(SIZE);
		if (sizeParameter != null) {
			try {
			    size = Integer.parseInt(sizeParameter);
			} catch (NumberFormatException n) {
			}
		}

		entry = -1;
		entryParameter = req.getParameter(ENTRY);
		if (entryParameter != null) {
			try {
			    entry = Integer.parseInt(entryParameter);
			} catch (NumberFormatException n) {
			}
		}

		modeParameter = req.getParameter(MODE);
		showAllParameter = req.getParameter(SHOW_ALL);
		if (showAllParameter != null) {
			// Use activities data to toggle the show all state
			new ActivitiesData(this.getServletContext(), req, resp);
		}

		req.setCharacterEncoding("UTF-8"); //$NON-NLS-1$
		// Cache suppression required because the set of in scope
		// topics could change between requests

		resp.setHeader("Cache-Control","no-cache");   //$NON-NLS-1$//$NON-NLS-2$
		resp.setHeader("Pragma","no-cache");  //$NON-NLS-1$ //$NON-NLS-2$
		resp.setDateHeader ("Expires", 0); 	 //$NON-NLS-1$

		AbstractHelpScope scope = RequestScope.getScope(req, resp, false);
		Serializer serializer = new Serializer(locale, scope);
		String response = serializer.generateIndexXml();
		locale2Response.put(locale, response);

		return response;
	}

	/*
	 * Class which creates the xml file based upon the request parameters
	 */
	private class Serializer {

		private IIndex index;
		private StringBuilder buf;
		private int count = 0;
		private String locale;
		private List<Integer> entryList;
		private IIndexEntry[] entries;
		private boolean enablePrevious = true;
		private boolean enableNext = true;
		private AbstractHelpScope scope;

		public Serializer(String locale, AbstractHelpScope scope) {
			this.locale = locale;
			this.scope = scope;
			index = HelpPlugin.getIndexManager().getIndex(locale);
			buf = new StringBuilder();
		}

		/*
		 * There are three modes of generation, current page, next page and previous page.
		 * Current page returns a screenful of entries starting at the startParameter.
		 * Next page returns a screenful of entries starting after but not including the start parameter.
		 * Previous page returns a screenful of entries going back from the start parameter
		 */
		private String generateIndexXml() {

			entries = index.getEntries();
			if (entries.length == 0) {
				generateEmptyIndexMessage();
			} else {
				entryList = new ArrayList<>();
				int nextEntry = findFirstEntry(entries);
				if (PREVIOUS.equals(modeParameter)) {
					int remaining = getPreviousEntries(nextEntry, size);
					getNextEntries(nextEntry, remaining);
				} else {
					int remaining = getNextEntries(nextEntry, size);
					if (remaining == size) {
						// Generate just the last entry
						size = 1;
						getPreviousEntries(nextEntry, 1);
					}
				}
				for (Integer entryId : entryList) {
					generateEntry(entries[entryId.intValue()], 0, "e" + entryId.intValue()); //$NON-NLS-1$
				}
			}
			String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tree_data enableNext = \"" //$NON-NLS-1$
				+ Boolean.toString(enableNext) + "\" enablePrevious = \"" + Boolean.toString(enablePrevious) + "\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
			buf.append("</tree_data>\n"); //$NON-NLS-1$
			return header + buf.toString();
		}

		private int getCategory(String keyword) {
			if (keyword != null && keyword.length() > 0) {
				char c = keyword.charAt(0);
				if (Character.isDigit(c)) {
					return 2;
				} else if (Character.isLetter(c)) {
					return 3;
				}
				return 1;
			}
			return 4;
		}

		private int compare (String left, String right) {
			int catLeft = getCategory(left);
			int catRight = getCategory(right);
			if (catLeft != catRight) {
				return catLeft - catRight;
			} else {
				return collator.compare(left, right);
			}
		}

		private int findFirstEntry(IIndexEntry[] entries) {
			if (NEXT.equals(modeParameter)) {
				if (entry >= entries.length - 1) {
					return entries.length - 1;
				} else {
					return entry + 1;
				}
			}
			if (PREVIOUS.equals(modeParameter)) {
				if (entry <= 0) {
					return 0;
				} else {
					return entry - 1;
				}
			}
			if (startParameter == null) {
				return 0;
			}
			int nextEntry = 0;
			while (nextEntry < entries.length) {
			    String keyword = entries[nextEntry].getKeyword().toLowerCase();
				if (keyword != null) {
					if (compare(startParameter, keyword) <= 0) {
				        break;
					}
				}
				nextEntry++;
			}
			return nextEntry;
		}

		private int getNextEntries(int nextEntry, int remaining) {
			while (nextEntry < entries.length) {
				int entrySize = enabledEntryCount(entries[nextEntry]);
				if (remaining == size || remaining > entrySize) {
                    entryList.add(Integer.valueOf(nextEntry));
                    setFlags(nextEntry);
                    remaining -= entrySize;
				} else {
					break;
				}
				nextEntry++;
			}
			return remaining;
		}

		private int getPreviousEntries(int nextEntry, int remaining) {
			nextEntry--;
			while (nextEntry >= 0) {
				int entrySize = enabledEntryCount(entries[nextEntry]);
				if (remaining == size || remaining > entrySize) {
                    entryList.add(0, Integer.valueOf(nextEntry));

                    setFlags(nextEntry);
                    remaining -= entrySize;
				} else {
					break;
				}
				nextEntry--;
			}
			return remaining;
		}

		private void setFlags(int nextEntry) {
			if (nextEntry == 0) {
				enablePrevious = false;
			}
			if (nextEntry == entries.length - 1) {
				enableNext = false;
			}
		}

		private int enabledEntryCount(IIndexEntry entry) {
			if (!ScopeUtils.showInTree(entry, scope)) return 0;
			if (entry.getKeyword() == null || entry.getKeyword().length() == 0) {
				return 0;
			}
			int count = 1;
		    int topicCount = enabledTopicCount(entry);

			IIndexEntry[] subentries = entry.getSubentries();
		    int subentryCount = 0;
			for (IIndexEntry subentrie : subentries) {
				count += enabledEntryCount(subentrie);
			}

			int seeCount = 0;
			IIndexSee[] sees = entry instanceof IIndexEntry2 ? ((IIndexEntry2)entry).getSees() : new IIndexSee[0];
			for (IIndexSee see : sees) {
				if (ScopeUtils.showInTree(see, scope)) {
					seeCount++;
				}
			}

			if (topicCount + subentryCount + seeCount > 1) {
				count += topicCount;
			}
			count += subentryCount;
			count += seeCount;
            return count;
		}

		private int enabledTopicCount(IIndexEntry entry) {
			int topicCount = 0;
		    ITopic[] topics = entry.getTopics();
		    for (ITopic topic : topics) {
		    	if (scope.inScope(topic)) {
		    		topicCount++;
		    	}
		    }
			return topicCount;
		}

		private void generateEmptyIndexMessage() {
			buf.append("<node"); //$NON-NLS-1$
			buf.append('\n' + "      title=\"" + XMLGenerator.xmlEscape(WebappResources.getString("IndexEmpty", UrlUtil.getLocale(locale))) + '"'); //$NON-NLS-1$ //$NON-NLS-2$
			buf.append('\n' + "      id=\"no_index\""); //$NON-NLS-1$
			buf.append(">\n"); //$NON-NLS-1$
			buf.append("</node>\n"); //$NON-NLS-1$
			enableNext = false;
			enablePrevious = false;
		}

		private void generateEntry(IIndexEntry entry, int level, String id) {
			if (!ScopeUtils.showInTree(entry, scope)) return;
			if (entry.getKeyword() != null && entry.getKeyword().length() > 0) {
				ITopic[] topics = ScopeUtils.inScopeTopics(entry.getTopics(), scope);
				IIndexEntry[] subentries = ScopeUtils.inScopeEntries(entry.getSubentries(), scope);
				IIndexSee[] sees;
				if (entry instanceof IIndexEntry2) {
					sees = ((IIndexEntry2)entry).getSees();
				} else {
					sees = new IIndexSee[0];
				}
				boolean multipleTopics = topics.length > 1;
				boolean singleTopic = topics.length == 1;

				buf.append("<node"); //$NON-NLS-1$
				if (entry.getKeyword() != null) {
					buf.append('\n' + "      title=\"" + XMLGenerator.xmlEscape(entry.getKeyword()) + '"'); //$NON-NLS-1$
				}

				buf.append('\n' + "      id=\"" + id + '"'); //$NON-NLS-1$

				String href;
				if (singleTopic) {
					href = UrlUtil.getHelpURL((topics[0]).getHref());
				    buf.append('\n' + "      href=\"" +  //$NON-NLS-1$
				    	XMLGenerator.xmlEscape(href) + "\""); //$NON-NLS-1$
				}
				buf.append(">\n"); //$NON-NLS-1$

				if (multipleTopics || subentries.length > 0 || sees.length > 0) {
					if (multipleTopics) generateTopicList(entry);
					generateSubentries(entry, level + 1);
					generateSees(sees);
				}

				buf.append("</node>\n"); //$NON-NLS-1$
			}
		}

		private void generateSubentries(IIndexEntry entry, int level) {
			IIndexEntry[] subentries = entry.getSubentries();
			for (IIndexEntry subentrie : subentries) {
				generateEntry(subentrie, level, "s" + count++); //$NON-NLS-1$
			}
		}

		private void generateTopicList(IIndexEntry entry) {
			ITopic[] topics = entry.getTopics();

			for (ITopic topic : topics) {
				if (ScopeUtils.showInTree(topic, scope)) {
					//
					String label = UrlUtil.htmlEncode(topic.getLabel());
					if (label == null) {
						label = UrlUtil.htmlEncode(topic.getLabel());
					}

					buf.append("<node"); //$NON-NLS-1$
					if (entry.getKeyword() != null) {
						buf.append('\n' + "      title=\"" + label + '"'); //$NON-NLS-1$
					}

					count++;
					buf.append('\n' + "      id=\"i" + count + '"'); //$NON-NLS-1$
					String href = UrlUtil.getHelpURL(topic.getHref());
					buf.append('\n' + "      href=\"" //$NON-NLS-1$
							+ XMLGenerator.xmlEscape(href) + "\""); //$NON-NLS-1$
					buf.append(">\n"); //$NON-NLS-1$
					buf.append("</node>\n"); //$NON-NLS-1$
				}
			}
		}

		private void generateSees(IIndexSee[] sees) {
	        for (IIndexSee see : sees) {
	        	if (ScopeUtils.showInTree(see, scope)) {
					//
					String key = see.isSeeAlso() ? "SeeAlso" : "See"; //$NON-NLS-1$ //$NON-NLS-2$
					String seePrefix = WebappResources.getString(key, UrlUtil
							.getLocale(locale));
					String seeTarget = see.getKeyword();
					IIndexSubpath[] subpathElements = see.getSubpathElements();
					for (IIndexSubpath subpathElement : subpathElements) {
						seeTarget += ", "; //$NON-NLS-1$
						seeTarget += subpathElement.getKeyword();
					}
					String label = NLS.bind(seePrefix, seeTarget);
					String encodedLabel = UrlUtil.htmlEncode(label);
					buf.append("<node"); //$NON-NLS-1$

					buf.append('\n' + "      title=\"" + encodedLabel + '"'); //$NON-NLS-1$

					count++;
					buf.append('\n' + "      id=\"i" + count + '"'); //$NON-NLS-1$
					String href = "see:" + seeTarget; //$NON-NLS-1$
					buf.append('\n' + "      href=\"" //$NON-NLS-1$
							+ XMLGenerator.xmlEscape(href) + "\""); //$NON-NLS-1$
					buf.append(">\n"); //$NON-NLS-1$
					buf.append("</node>\n"); //$NON-NLS-1$
	        	}
	        }
		}
	}

}
