/*******************************************************************************
 * Copyright (c) 2006, 2015 Red Hat, Inc. and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Red Hat Incorporated - initial API and implementation
 *     Ed Swartz (NOKIA) - updates
 *******************************************************************************/
package org.eclipse.cdt.autotools.ui.editors;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.autotools.core.AutotoolsPlugin;
import org.eclipse.cdt.internal.autotools.ui.preferences.AutotoolsEditorPreferenceConstants;
import org.eclipse.cdt.internal.autotools.ui.preferences.ColorManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WhitespaceRule;
import org.eclipse.jface.text.rules.WordRule;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;

public class AutoconfCodeScanner extends RuleBasedScanner {

	private Map<String, IToken> fTokenMap = new HashMap<>();
	private String[] fPropertyNamesColor;

	/**
	 * Preference keys for boolean preferences which are <code>true</code>,
	 * iff the corresponding token should be rendered bold.
	 */
	private String[] fPropertyNamesBold;
	/**
	 * Preference keys for boolean preferences which are <code>true</code>,
	 * iff the corresponding token should be rendered italic.
	 */
	private String[] fPropertyNamesItalic;

	private static String[] keywords = { "case", "do", "done", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			"esac", "if", "elif", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			"else", "fi", "for", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			"in", "then" }; //$NON-NLS-1$ //$NON-NLS-2$

	static final String[] fTokenProperties = new String[] { ColorManager.AUTOCONF_COMMENT_COLOR,
			ColorManager.AUTOCONF_KEYWORD_COLOR, ColorManager.AUTOCONF_ACMACRO_COLOR,
			ColorManager.AUTOCONF_AMMACRO_COLOR, ColorManager.AUTOCONF_VAR_REF_COLOR,
			ColorManager.AUTOCONF_VAR_SET_COLOR, ColorManager.AUTOCONF_CODESEQ_COLOR,
			ColorManager.AUTOCONF_DEFAULT_COLOR, };

	public AutoconfCodeScanner() {

		initialize();

		IToken other = getToken(ColorManager.AUTOCONF_DEFAULT_COLOR);
		IToken keyword = getToken(ColorManager.AUTOCONF_KEYWORD_COLOR);
		IToken comment = getToken(ColorManager.AUTOCONF_COMMENT_COLOR);
		IToken string = getToken(ColorManager.AUTOCONF_DEFAULT_COLOR);
		IToken varRef = getToken(ColorManager.AUTOCONF_VAR_REF_COLOR);
		IToken acmacro = getToken(ColorManager.AUTOCONF_ACMACRO_COLOR);
		IToken ammacro = getToken(ColorManager.AUTOCONF_AMMACRO_COLOR);
		IToken code = getToken(ColorManager.AUTOCONF_CODESEQ_COLOR);

		List<IRule> rules = new ArrayList<>();

		// Add rule for single line comments.
		rules.add(new EndOfLineRule("dnl", comment)); //$NON-NLS-1$
		rules.add(new EndOfLineRule("#", comment, '\\')); //$NON-NLS-1$

		// Add special recursive rule for strings which allows variable
		// references to be internally tokenized.
		RecursiveSingleLineRule stringRule = new RecursiveSingleLineRule("\"", "\"", string, '\\'); //$NON-NLS-1$ //$NON-NLS-2$
		stringRule.addRule(new SingleLineRule("${", "}", varRef)); //$NON-NLS-1$ //$NON-NLS-2$
		rules.add(stringRule);

		// Add rule for variable references
		rules.add(new SingleLineRule("${", "}", varRef)); //$NON-NLS-1$ //$NON-NLS-2$
		// Add rule for strings
		rules.add(new SingleLineRule("\"", "\"", string, '\\')); //$NON-NLS-1$ //$NON-NLS-2$

		// Add rule for PKG_ macros
		rules.add(new AutoconfMacroRule("PKG_", new AutoconfPKGWordDetector(), acmacro)); //$NON-NLS-1$

		// Add rule for AC_ macros
		rules.add(new AutoconfMacroRule("AC_", new AutoconfMacroWordDetector(), acmacro)); //$NON-NLS-1$

		// Add rule for AM_ macros
		rules.add(new AutoconfMacroRule("AM_", new AutoconfMacroWordDetector(), ammacro)); //$NON-NLS-1$

		// Add rule for m4_ macros
		rules.add(new AutoconfMacroRule("m4_", new AutoconfM4WordDetector(), acmacro)); //$NON-NLS-1$

		// Add rule for code sequences starting with <<EOF and ending with EOF
		rules.add(new InlineDataRule(code));

		// Add word rule for keywords.
		WordRule wordRule = new WordRule(new AutoconfWordDetector(), Token.UNDEFINED);
		for (int i = 0; i < keywords.length; i++)
			wordRule.addWord(keywords[i], keyword);
		rules.add(wordRule);

		// Add word rule for identifier.
		rules.add(new AutoconfIdentifierRule(other));

		// Make sure we don't treat "\#" as comment start.
		rules.add(new SingleLineRule("\\#", null, Token.UNDEFINED)); //$NON-NLS-1$

		rules.add(new WhitespaceRule(new AutoconfWhitespaceDetector()));

		setDefaultReturnToken(other);

		IRule[] result = new IRule[rules.size()];
		rules.toArray(result);
		setRules(result);
	}

	protected Token getToken(String key) {
		return (Token) fTokenMap.get(key);
	}

	private void addToken(String colorKey, String boldKey, String italicKey) {
		fTokenMap.put(colorKey, new Token(createTextAttribute(colorKey, boldKey, italicKey)));
	}

	protected String[] getTokenProperties() {
		return fTokenProperties;
	}

	private int indexOf(String property) {
		if (property != null) {
			int length = fPropertyNamesColor.length;
			for (int i = 0; i < length; i++) {
				if (property.equals(fPropertyNamesColor[i]) || property.equals(fPropertyNamesBold[i])
						|| property.equals(fPropertyNamesItalic[i]))
					return i;
			}
		}
		return -1;
	}

	public boolean affectsBehavior(PropertyChangeEvent event) {
		return indexOf(event.getProperty()) >= 0;
	}

	public void adaptToPreferenceChange(PropertyChangeEvent event) {
		String p = event.getProperty();
		int index = indexOf(p);
		Token token = getToken(fPropertyNamesColor[index]);
		if (fPropertyNamesColor[index].equals(p))
			adaptToColorChange(event, token);
		else if (fPropertyNamesBold[index].equals(p))
			adaptToStyleChange(event, token, SWT.BOLD);
		else if (fPropertyNamesItalic[index].equals(p))
			adaptToStyleChange(event, token, SWT.ITALIC);
	}

	protected void adaptToColorChange(PropertyChangeEvent event, Token token) {
		RGB rgb = null;
		Object value = event.getNewValue();
		if (value instanceof RGB) {
			rgb = (RGB) value;
		} else if (value instanceof String) {
			rgb = StringConverter.asRGB((String) value);
		}

		if (rgb != null) {
			TextAttribute attr = (TextAttribute) token.getData();
			token.setData(
					new TextAttribute(ColorManager.getDefault().getColor(rgb), attr.getBackground(), attr.getStyle()));
		}
	}

	protected void adaptToStyleChange(PropertyChangeEvent event, Token token, int styleAttribute) {
		if (token == null) {
			return;
		}
		boolean eventValue = false;
		Object value = event.getNewValue();
		if (value instanceof Boolean) {
			eventValue = ((Boolean) value).booleanValue();
		} else if (IPreferenceStore.TRUE.equals(value)) {
			eventValue = true;
		}

		TextAttribute attr = (TextAttribute) token.getData();
		boolean activeValue = (attr.getStyle() & styleAttribute) == styleAttribute;
		if (activeValue != eventValue) {
			token.setData(new TextAttribute(attr.getForeground(), attr.getBackground(),
					eventValue ? attr.getStyle() | styleAttribute : attr.getStyle() & ~styleAttribute));
		}
	}

	protected TextAttribute createTextAttribute(String colorID, String boldKey, String italicKey) {
		Color color = null;
		if (colorID != null) {
			color = AutoconfEditor.getPreferenceColor(colorID);
		}
		IPreferenceStore store = AutotoolsPlugin.getDefault().getPreferenceStore();
		int style = store.getBoolean(boldKey) ? SWT.BOLD : SWT.NORMAL;
		if (store.getBoolean(italicKey)) {
			style |= SWT.ITALIC;
		}
		return new TextAttribute(color, null, style);
	}

	/**
	 * Must be called after the constructor has been called.
	 */
	public final void initialize() {

		fPropertyNamesColor = getTokenProperties();
		int length = fPropertyNamesColor.length;
		fPropertyNamesBold = new String[length];
		fPropertyNamesItalic = new String[length];

		for (int i = 0; i < length; i++) {
			fPropertyNamesBold[i] = fPropertyNamesColor[i] + AutotoolsEditorPreferenceConstants.EDITOR_BOLD_SUFFIX;
			fPropertyNamesItalic[i] = fPropertyNamesColor[i] + AutotoolsEditorPreferenceConstants.EDITOR_ITALIC_SUFFIX;
			addToken(fPropertyNamesColor[i], fPropertyNamesBold[i], fPropertyNamesItalic[i]);
		}
	}

	@Override
	public void unread() {
		--fOffset;
		fColumn = UNDEFINED;
	}
}
