/*******************************************************************************
 * Copyright (c) 2007, 2013 David Green 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:
 *     David Green - initial API and implementation
 *******************************************************************************/
package org.eclipse.mylyn.internal.wikitext.ui.editor.syntax;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.mylyn.internal.wikitext.ui.WikiTextUiPlugin;
import org.eclipse.mylyn.internal.wikitext.ui.editor.preferences.Preferences;
import org.eclipse.mylyn.internal.wikitext.ui.editor.syntax.FastMarkupPartitioner.MarkupPartition;
import org.eclipse.mylyn.internal.wikitext.ui.viewer.CssStyleManager;
import org.eclipse.mylyn.internal.wikitext.ui.viewer.FontState;
import org.eclipse.mylyn.wikitext.parser.css.CssParser;
import org.eclipse.mylyn.wikitext.parser.css.CssRule;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Font;

/**
 * A token scanner that uses the results of the {@link FastMarkupPartitioner} to identify tokens.
 *
 * @author David Green
 */
public class MarkupTokenScanner implements ITokenScanner {

	private Token currentToken = null;

	private Iterator<Token> tokenIt = null;

	private CssStyleManager styleManager;

	private FontState defaultState;

	private Preferences preferences;

	private final CssParser cssParser = new CssParser();

	public MarkupTokenScanner(Font defaultFont, Font defaultMonospaceFont) {
		initialize(defaultFont, defaultMonospaceFont);
		reloadPreferences();
	}

	/**
	 * Reset the fonts used by this token scanner.
	 *
	 * @param defaultFont
	 *            the default font, must not be null.
	 * @param defaultMonospaceFont
	 *            the default monospace font, or null if a suitable default should be selected
	 */
	public void resetFonts(Font defaultFont, Font defaultMonospaceFont) {
		if (defaultFont == null) {
			throw new IllegalArgumentException();
		}
		initialize(defaultFont, defaultMonospaceFont);
	}

	private void initialize(Font defaultFont, Font defaultMonospaceFont) {
		styleManager = new CssStyleManager(defaultFont, defaultMonospaceFont);
		defaultState = styleManager.createDefaultFontState();
	}

	public void reloadPreferences() {
		preferences = WikiTextUiPlugin.getDefault().getPreferences();
	}

	public int getTokenLength() {
		return currentToken == null ? -1 : currentToken.getLength();
	}

	public int getTokenOffset() {
		return currentToken == null ? -1 : currentToken.getOffset();
	}

	public IToken nextToken() {
		if (tokenIt != null && tokenIt.hasNext()) {
			currentToken = tokenIt.next();
		} else {
			currentToken = null;
			tokenIt = null;
			return org.eclipse.jface.text.rules.Token.EOF;
		}
		return currentToken;
	}

	public void setRange(IDocument document, int offset, int length) {
		IDocumentPartitioner partitioner = document.getDocumentPartitioner();
		List<Token> tokens = null;

		if (partitioner instanceof FastMarkupPartitioner) {
			FastMarkupPartitioner fastMarkupPartitioner = (FastMarkupPartitioner) partitioner;
			ITypedRegion[] partitioning = partitioner.computePartitioning(offset, length);
			if (partitioning != null) {
				tokens = new ArrayList<>();

				ITypedRegion[] partitions = ((FastMarkupPartitioner) partitioner).getScanner()
						.computePartitions(document, offset, length);
				int lastEnd = offset;

				Token defaultToken;
				{
					StyleRange styleRange = styleManager.createStyleRange(defaultState, 0, 1);
					TextAttribute textAttribute = createTextAttribute(styleRange);
					defaultToken = new Token(defaultState, textAttribute, offset, length);
				}
				if (partitions != null) {
					for (ITypedRegion region : partitions) {
						if (region.getOffset() >= (offset + length)) {
							break;
						}
						if ((region.getOffset() + region.getLength()) < offset) {
							continue;
						}
						if (region instanceof MarkupPartition) {
							MarkupPartition partition = (MarkupPartition) region;

							if (lastEnd < partition.getOffset()) {
								Token blockBridgeToken = new Token(defaultToken.fontState, defaultToken.getData(),
										lastEnd, partition.getOffset() - lastEnd);
								addToken(tokens, blockBridgeToken);
							}

							// a token that spans the whole block
							Token blockToken = createToken(partition);
							if (blockToken == null) {
								blockToken = defaultToken;
							}
							if (!partition.getBlock().isSpansComputed()) {
								fastMarkupPartitioner.reparse(document, partition.getBlock());
							}
							List<Span> spans = partition.getSpans();
							if (spans != null) {
								for (Span span : spans) {
									if (span.getOffset() < lastEnd) {
										continue;
									}
									Token spanToken = createToken(blockToken.getFontState(), span);
									if (spanToken != null) {
										int blockTokenStartOffset = lastEnd < offset ? offset : lastEnd;
										if (blockTokenStartOffset < spanToken.getOffset()) {
											int blockTokenLength = spanToken.getOffset() - blockTokenStartOffset;
											final Token blockBridgeToken = new Token(blockToken.fontState,
													blockToken.getData(), blockTokenStartOffset, blockTokenLength);
											addToken(tokens, blockBridgeToken);
										}

										Token[] spanTokens = null;
										if (!span.getChildren().isEmpty()) {
											spanTokens = splitSpan(spanToken, span, defaultToken);
										}
										if (spanTokens != null) {
											for (Token spanSplitToken : spanTokens) {
												addToken(tokens, spanSplitToken);
											}
										} else {
											addToken(tokens, spanToken);
										}
										lastEnd = spanToken.offset + spanToken.length;
										if (lastEnd > partition.getOffset() + partition.getLength()) {
											throw new IllegalStateException();
										}
									}
								}
							}
							final int partitionEnd = partition.getOffset() + partition.getLength();
							if (lastEnd < partitionEnd) {
								final int realLastEnd = Math.max(lastEnd, partition.getOffset());
								int diff = (partitionEnd) - realLastEnd;
								if (diff > 0) {
									int blockTokenStartOffset = realLastEnd;
									int blockTokenLength = diff;
									final Token blockBridgeToken = new Token(blockToken.fontState, blockToken.getData(),
											blockTokenStartOffset, blockTokenLength);
									addToken(tokens, blockBridgeToken);
									lastEnd = blockTokenStartOffset + blockTokenLength;
									if (lastEnd > partition.getOffset() + partition.getLength()) {
										throw new IllegalStateException();
									}
								}
							}
						}
					}
				}
				if (lastEnd < (offset + length)) {
					addToken(tokens, new Token(defaultToken.fontState, defaultToken.getData(), lastEnd,
							length - (lastEnd - offset)));
				}
			}
		}

		currentToken = null;
		if (tokens == null || tokens.isEmpty()) {
			tokenIt = null;
		} else {
			Iterator<Token> it = tokens.iterator();
			while (it.hasNext()) {
				Token next = it.next();
				if (next.getOffset() < offset) {
					it.remove();
				} else if (next.getOffset() + next.getLength() > (offset + length)) {
					it.remove();
				}
			}
			tokenIt = tokens.iterator();
		}

	}

	protected TextAttribute createTextAttribute(StyleRange styleRange) {
		int fontStyle = styleRange.fontStyle;
		if (styleRange.strikeout) {
			fontStyle |= TextAttribute.STRIKETHROUGH;
		}
		if (styleRange.underline) {
			fontStyle |= TextAttribute.UNDERLINE;
		}
		return new TextAttribute(styleRange.foreground, styleRange.background, fontStyle, styleRange.font);
	}

	/**
	 * handle nested spans: given a token for a specific span, split it into one or more tokens based on analyzing its
	 * children
	 *
	 * @return an array of tokens that contiguously cover the region represented by the original span.
	 */
	private Token[] splitSpan(Token spanToken, Span span, Token defaultToken) {
		List<Token> tokens = new ArrayList<>(span.getChildren().size() + 1);
		int previousEnd = spanToken.offset;
		for (Span child : span.getChildren().asList()) {
			if (child.getOffset() > previousEnd) {
				tokens.add(new Token(spanToken.fontState, spanToken.getData(), previousEnd,
						child.getOffset() - previousEnd));
			}
			Token childToken = createToken(spanToken.fontState, child);
			if (childToken == null) {
				StyleRange styleRange = styleManager.createStyleRange(spanToken.fontState, 0, 1);
				TextAttribute textAttribute = createTextAttribute(styleRange);
				childToken = new Token(spanToken.fontState, textAttribute, child.getOffset(), child.getLength());
			}
			if (child.getChildren().isEmpty()) {
				tokens.add(childToken);
			} else {
				// recursively apply to children
				for (Token t : splitSpan(childToken, child, defaultToken)) {
					tokens.add(t);
				}
			}
			previousEnd = child.getEndOffset();
		}
		if (previousEnd < span.getEndOffset()) {
			tokens.add(new Token(spanToken.fontState, spanToken.getData(), previousEnd,
					span.getEndOffset() - previousEnd));
		}
		return tokens.toArray(new Token[tokens.size()]);
	}

	private void addToken(List<Token> tokens, Token newToken) {
		checkAddToken(tokens, newToken);
		tokens.add(newToken);
	}

	private void checkAddToken(List<Token> tokens, Token newToken) {
		if (newToken.getLength() <= 0) {
			throw new IllegalStateException(
					NLS.bind(Messages.MarkupTokenScanner_badTokenLength, new Object[] { newToken.getLength() }));
		}
		if (newToken.getOffset() < 0) {
			throw new IllegalStateException(
					NLS.bind(Messages.MarkupTokenScanner_badTokenOffset, new Object[] { newToken.getOffset() }));
		}
		if (!tokens.isEmpty()) {
			Token previous = tokens.get(tokens.size() - 1);
			if (previous.getOffset() >= newToken.getOffset()) {
				throw new IllegalStateException(Messages.MarkupTokenScanner_2);
			} else if (previous.getOffset() + previous.getLength() > newToken.getOffset()) {
				throw new IllegalStateException(Messages.MarkupTokenScanner_3);
			}
		}
	}

	private Token createToken(FontState parentState, Span span) {
		if (span.getLength() == 0) {
			return null;
		}
		String cssStyles = null;
		String key = null;
		switch (span.getType()) {
		case BOLD:
			key = Preferences.PHRASE_BOLD;
			break;
		case CITATION:
			key = Preferences.PHRASE_CITATION;
			break;
		case CODE:
			key = Preferences.PHRASE_CODE;
			break;
		case DELETED:
			key = Preferences.PHRASE_DELETED_TEXT;
			break;
		case EMPHASIS:
			key = Preferences.PHRASE_EMPHASIS;
			break;
		case INSERTED:
			key = Preferences.PHRASE_INSERTED_TEXT;
			break;
		case ITALIC:
			key = Preferences.PHRASE_ITALIC;
			break;
		case MONOSPACE:
			key = Preferences.PHRASE_MONOSPACE;
			break;
		case QUOTE:
			key = Preferences.PHRASE_QUOTE;
			break;
		case SPAN:
			key = Preferences.PHRASE_SPAN;
			break;
		case STRONG:
			key = Preferences.PHRASE_STRONG;
			break;
		case SUBSCRIPT:
			key = Preferences.PHRASE_SUBSCRIPT;
			break;
		case SUPERSCRIPT:
			key = Preferences.PHRASE_SUPERSCRIPT;
			break;
		case UNDERLINED:
			key = Preferences.PHRASE_UNDERLINED;
			break;
		}
		cssStyles = preferences.getCssByPhraseModifierType().get(key);
		if (cssStyles == null && span.getAttributes().getCssStyle() == null && span.getChildren().isEmpty()) {
			return null;
		}
		FontState fontState = new FontState(parentState);
		if (cssStyles != null) {
			processCssStyles(fontState, parentState, cssStyles);
		}
		if (span.getAttributes().getCssStyle() != null) {
			processCssStyles(fontState, parentState, span.getAttributes().getCssStyle());
		}
		StyleRange styleRange = styleManager.createStyleRange(fontState, 0, 1);

		TextAttribute textAttribute = createTextAttribute(styleRange);
		return new Token(fontState, textAttribute, span.getOffset(), span.getLength());
	}

	private Token createToken(MarkupPartition partition) {
		if (partition.getLength() == 0) {
			return null;
		}
		FontState fontState = new FontState(defaultState);
		boolean hasStyles = processStyles(partition.getBlock(), partition, fontState);

		if (partition.getBlock().getAttributes().getCssStyle() != null) {
			processCssStyles(fontState, defaultState, partition.getBlock().getAttributes().getCssStyle());
		} else {
			if (!hasStyles) {
				return null;
			}
		}
		StyleRange styleRange = styleManager.createStyleRange(fontState, 0, 1);

		TextAttribute textAttribute = createTextAttribute(styleRange);
		return new Token(fontState, textAttribute, partition.getOffset(), partition.getLength());
	}

	private boolean processStyles(Block block, MarkupPartition partition, FontState fontState) {
		boolean hasStyles = false;
		if (block.getParent() != null) {
			hasStyles = processStyles(block.getParent(), partition, fontState);
		}
		String cssStyles = computeCssStyles(block, partition);
		if (cssStyles != null) {
			hasStyles = true;
			processCssStyles(fontState, defaultState, cssStyles);
		}
		return hasStyles;
	}

	private String computeCssStyles(Block block, MarkupPartition partition) {
		String cssStyles = null;
		if (block.getHeadingLevel() > 0) {
			cssStyles = preferences.getCssByBlockModifierType()
					.get(Preferences.HEADING_PREFERENCES[block.getHeadingLevel()]);
		} else if (block.getType() != null) {
			String key = null;
			switch (block.getType()) {
			case CODE:
				key = Preferences.BLOCK_BC;
				break;
			case QUOTE:
				key = Preferences.BLOCK_QUOTE;
				break;
			case PREFORMATTED:
				key = Preferences.BLOCK_PRE;
				break;
			case DEFINITION_TERM:
				key = Preferences.BLOCK_DT;
				break;
			}
			cssStyles = preferences.getCssByBlockModifierType().get(key);
		}
		return cssStyles;
	}

	private void processCssStyles(FontState fontState, FontState parentState, String cssStyles) {
		Iterator<CssRule> ruleIterator = cssParser.createRuleIterator(cssStyles);
		while (ruleIterator.hasNext()) {
			styleManager.processCssStyles(fontState, parentState, ruleIterator.next());
		}
	}

	/**
	 * public for testing purposes
	 */
	public static class Token extends org.eclipse.jface.text.rules.Token {

		private final int offset;

		private final int length;

		private final FontState fontState;

		public Token(FontState fontState, TextAttribute attribute, int offset, int length) {
			super(attribute);
			this.fontState = fontState;
			if (offset < 0) {
				throw new IllegalArgumentException();
			}
			if (length < 0) {
				throw new IllegalArgumentException();
			}
			this.offset = offset;
			this.length = length;
		}

		public int getOffset() {
			return offset;
		}

		public int getLength() {
			return length;
		}

		public FontState getFontState() {
			return fontState;
		}

		@Override
		public TextAttribute getData() {
			return (TextAttribute) super.getData();
		}

		@Override
		public String toString() {
			return "Token [offset=" + offset + ", length=" + length + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

	}

}
