/*******************************************************************************
 * Copyright (c) 2009, 2019 Xored Software Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.tesla.recording.core.internal.ecl;

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

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.rcptt.ecl.core.Command;
import org.eclipse.rcptt.ecl.core.Pipeline;
import org.eclipse.rcptt.ecl.core.util.ScriptletFactory;
import org.eclipse.rcptt.tesla.core.protocol.ElementKind;
import org.eclipse.rcptt.tesla.core.protocol.IMLSelectData;
import org.eclipse.rcptt.tesla.core.protocol.IWindowProvider;
import org.eclipse.rcptt.tesla.core.protocol.SelectCommand;
import org.eclipse.rcptt.tesla.core.protocol.SelectData;
import org.eclipse.rcptt.tesla.core.protocol.raw.CommandToElementEntry;
import org.eclipse.rcptt.tesla.core.protocol.raw.Element;
import org.eclipse.rcptt.tesla.core.protocol.raw.TeslaScenario;
import org.eclipse.rcptt.tesla.core.utils.TeslaPathUtils;
import org.eclipse.rcptt.tesla.ecl.TeslaScriptletFactory;
import org.eclipse.rcptt.tesla.ecl.model.GetColumnHeader;
import org.eclipse.rcptt.tesla.ecl.model.GetEclipseWindow;
import org.eclipse.rcptt.tesla.ecl.model.GetPropertyTab;
import org.eclipse.rcptt.tesla.ecl.model.GetRegion;
import org.eclipse.rcptt.tesla.ecl.model.Selector;
import org.eclipse.rcptt.tesla.ecl.model.TeslaFactory;
import org.eclipse.rcptt.tesla.ecl.model.TeslaPackage;
import org.eclipse.rcptt.tesla.recording.core.ecl.ISelectorParserExtension;
import org.eclipse.rcptt.tesla.recording.core.ecl.TeslaRecordingPlugin;
import org.eclipse.rcptt.tesla.recording.core.ecl.parser.TeslaParserUtil;
import org.eclipse.rcptt.util.Base64;

public class TeslaSelectorParser extends TeslaScriptletFactory {

	private static final String EXTENSION_ID = "org.eclipse.rcptt.tesla.recording.core.ecl.selectorExtension"; //$NON-NLS-1$
	static final List<ISelectorParserExtension> extensions = new ArrayList<ISelectorParserExtension>();

	static {
		initExtensions();
	}

	private static void initExtensions() {
		IConfigurationElement[] config = Platform.getExtensionRegistry()
				.getConfigurationElementsFor(EXTENSION_ID);
		try {
			for (IConfigurationElement element : config) {
				final Object extension = element
						.createExecutableExtension("class"); //$NON-NLS-1$
				if (extension instanceof ISelectorParserExtension) {
					extensions.add((ISelectorParserExtension) extension);
				}
			}
		} catch (CoreException e) {
			TeslaRecordingPlugin.log("Error while get selector extension.", e); //$NON-NLS-1$			
		}
	}

	//

	protected Map<String, Command> elements = new HashMap<String, Command>();
	protected TeslaScenario scenario;

	public TeslaSelectorParser(TeslaScenario scenario) {
		this.scenario = scenario;
	}

	public void parse() {
		init();
		process();
	}

	protected void init() {
	}

	protected void process() {
		List<CommandToElementEntry> entries = scenario.getElementMapping();
		for (CommandToElementEntry entry : entries) {
			org.eclipse.rcptt.tesla.core.protocol.raw.Command command = entry.getCommand();
			if (command instanceof SelectCommand) {
				String id = entry.getElements().get(0).getId();
				Command e = element((SelectCommand) command, id);
				if (e != null) {
					save(id, e);
				}
			}
		}
	}

	protected void save(String id, Command e) {
		Command oldVal = elements.put(id, e);
		if (oldVal != null && !EcoreUtil.equals(e, oldVal))
			throw new IllegalArgumentException("Elements with duplicate id=" + id + " are detected");
	}

	protected Command element(SelectCommand command, String id) {
		SelectData data = command.getData();
		if (data.getKind().equals("CompositeRuler")) {
			data.setKind(ElementKind.VerticalRuler.name());
		}
		if (data.getKind().equals("OverviewRuler")) {
			data.setKind(ElementKind.RightRuler.name());
		}
		ElementKind kind = ElementKind.kindOf(data.getKind());
		if (kind == null) {
			throw new IllegalArgumentException("Null-kind control was detected");
		}
		if (kind == ElementKind.Item) {
			List<Integer> indexes = data.getIndexes();
			if (indexes == null || indexes.isEmpty()) {
				Command selector = TeslaParserUtil.makeItem(data.getPath());
				// index and after are not recorded for items, so skip them
				Command parent = selectorOf(data.getParent());
				if (parent != null) {
					return makePipe(parent, selector);
				}
				return selector;
			}
		}
		if (kind == ElementKind.Menu) {
			Command selector = TeslaParserUtil.makeMenu(data.getPath(), data.getIndex());
			// index and after are not recorded for menus, so skip them
			Command parent = selectorOf(data.getParent());
			if (parent != null) {
				return makePipe(parent, selector);
			}
			return selector;
		}

		Selector selector = null;

		if (kind == ElementKind.Custom) {
			// Try get selector from extensions
			for (ISelectorParserExtension extension : extensions) {
				selector = extension.selector(
						data.getKind(), data.getPattern(), data.getPath(), data.getIndexes());
				if (selector != null) {
					break;
				}
			}
		}
		if (selector == null) {
			selector = selector(kind, data);
		}

		if (kind.equals(ElementKind.Region) && data instanceof IMLSelectData) {
			selector = selector(kind, ((IMLSelectData) data).getImage(),
					data.getIndexes());
		}
		if (selector == null)
			return null;
		selector.setId(id);
		selector.setIndex(data.getIndex());
		Command parent = selectorOf(data.getParent());
		Command after = selectorOf(data.getAfter());
		if (after instanceof Pipeline) {
			if (parent != null) {
				Command cutAfter = TeslaParserUtil.cut(after, parent);
				if (cutAfter == null) {
					// FIXME workaround for suspicious selectors bug
					EList<Command> afterCommands = ((Pipeline) after)
							.getCommands();
					if (afterCommands.size() > 1) {
						after = afterCommands.get(afterCommands.size() - 1);
					}
				} else {
					after = cutAfter;
				}
			}
		}
		if (after != null) {
			ScriptletFactory.bind(selector,
					TeslaPackage.eINSTANCE.getSelector_After(), after);
		}
		if (parent != null) {
			return makePipe(parent, selector);
		}
		return selector;
	}

	private Selector selector(ElementKind kind, byte[] image,
			EList<Integer> indexes) {
		switch (kind) {
		case Region:
			GetRegion region = makeRegion();
			region.setImageURI("base64://");
			region.setRawImage(Base64.encode(image));
			region.setX(indexes.get(0));
			region.setY(indexes.get(1));
			return region;
		}
		return null;
	}

	protected Selector selector(ElementKind kind, SelectData data) {

		String text = data.getPattern();
		List<String> path = data.getPath();
		List<Integer> indexes = data.getIndexes();
		Integer index = data.getIndex();

		switch (kind) {
		case Button:
			return makeButton(text);
		case Canvas:
			return makeCanvas();
		case CBanner:
			return makeCBanner();
		case Combo:
			return makeCombo();
		case CoolBar:
			return makeCoolbar();
		case DiagramViewer:
			return makeDiagramViewer(index);
		case DiagramFigure:
			if (path.size() == 2) {
				String first = path.get(0);
				String second = path.get(1);
				if ("editpart".equals(first) && "address".equals(second)) {
					return makeEditPart(indexes);
				} else if ("editpart.source.connection".equals(first)
						&& "address".equals(second)) {
					return makeSourceConnection(indexes);
				} else if ("editpart.feature".equals(first)) {
					return makeEditPartByFeature(second, text);
				} else if ("editpart".equals(first)
						&& "customId".equals(second)) {
					return makeEditPartByCustomId(text);
				} else if ("editpart".equals(first)
						&& "classname".equals(second)) {
					return makeEditPartByClassName(text);
				} else if ("handle".equals(first) && "class".equals(second)) {
					return makeHandle(text);
				} else if ("editpart".equals(first) && "name".equals(second)) {
					return makeEditPartByName(text);
				} else if ("editpart".equals(first) && "text".equals(second)) {
					return makeEditPartByText(text);
				} else if ("editpart.target.connection".equals(first)
						&& "address".equals(second)) {
					return makeTargetConnection(indexes);
				} else if ("rawFigure".equals(first)
						&& "address".equals(second)) {
					if (indexes.size() > 0) {
						int value = indexes.get(0);
						switch (value) {
						case -3:
							// Popup bar
							return makePopupBarItem(indexes);
						case -2:
							// Connection
							return makeConnectionHandle(indexes);
						}
					}
					return makeFigure(indexes);
				}
			}
			throw new IllegalArgumentException("Unexpected figure path: "
					+ path.toArray(new String[0]).toString());
		case EclipseWindow:
			if (index != null && index.intValue() != 0) {
				return makeEclipseWindow(index.intValue());
			}
			return null; // do nothing
		case QuickAccess:
			return makeQuickAccess();
		case Editor:
			return makeEditor(text, data.getClassPattern(), index);
		case TextViewer:
			return makeTextViewer();
		case VerticalRuler:
			return makeVerticalRuler();
		case VerticalColumn:
			return makeRulerColumn(text);
		case LeftRuler:
			return makeLeftRuler();
		case RightRuler:
			return makeRightRuler();
		case Expandable:
			return makeExpandable(text);
		case FormText:
			return makeLabel(text);
		case Group:
			return makeGroup(text);
		case Item:
			if (indexes != null && !indexes.isEmpty()) {
				// It's cell
				if (indexes.size() != 2)
					throw new IllegalArgumentException("Invalid cell selector");
				return makeCell(indexes.get(1), indexes.get(0));
			}
			return makeItem(TeslaPathUtils.makePathFromList(path), null);
		case Label:
			return makeLabel(text);
		case Link:
			return makeLink(text);
		case List:
			return makeList();
		case Menu:
			return makeMenu(TeslaPathUtils.makePathFromList(path), index);
		case PaletteViewer:
			return makePaletteViewer();
		case State:
			return null;
		case TabFolder:
			return makeTabFolder();
		case TabItem:
			return makeTabItem(text);
		case Table:
			return makeTable();
		case Text:
			return makeEditbox();
		case Toolbar:
			return makeToolbar();
		case Tree:
			return makeTree();
		case DateTime:
			return makeDateTime();
		case Slider:
			return makeSlider();
		case View:
			return makeView(text);
		case Window: {
			if (path.size() == 2) {
				String first = path.get(0);
				String second = path.get(1);
				if (IWindowProvider.FROM_PATH_MARK.equals(first)) {
					return makeFromedWindow(second);
				} else if (IWindowProvider.CLASS_PATH_MARK.equals(first)) {
					return makeClassedWindow(second);
				}
			}
			return makeWindow(text);
		}
		case PaletteEntry:
			return paletteEntry(text);
		case ColumnHeader:
			return makeColumnHeader(text, index);
		case PropertyTab:
			return makePropertyTab(text);
		case Custom:
			return makeControl(data.getKind(), text);
		default:
			return makeControl(kind.name(), text);
		}
	}

	private Selector makePropertyTab(String text) {
		GetPropertyTab getPropertyTab = TeslaFactory.eINSTANCE
				.createGetPropertyTab();
		getPropertyTab.setText(text);
		return getPropertyTab;
	}

	private Selector makeColumnHeader(String text, Integer index) {
		GetColumnHeader getColumnHeader = TeslaFactory.eINSTANCE
				.createGetColumnHeader();
		getColumnHeader.setText(text);
		getColumnHeader.setIndex(index);
		return getColumnHeader;
	}

	public Command selectorOf(Element element) {
		return selectorOf(element, true);
	}

	public Command selectorOf(Element element, boolean reduceEclipseWindow) {
		if (element == null)
			return null;
		String id = element.getId();
		Command selector = elements.get(id);
		if (ElementKind.EclipseWindow.name().equals(element.getKind())
				&& selector instanceof GetEclipseWindow
				&& (((GetEclipseWindow) selector).getIndex() == null || ((GetEclipseWindow) selector)
						.getIndex().intValue() == 0)) {
			if (reduceEclipseWindow) {
				return null;
			}
		}
		if (selector == null) {
			if (ElementKind.EclipseWindow.name().equals(element.getKind())) {
				if (reduceEclipseWindow) {
					return null;
				}
				return TeslaFactory.eINSTANCE.createGetEclipseWindow();
			}
			return TeslaScriptletFactory.controlNotFound();
		}

		if (element.getKind() != null
				&& element.getKind().equals(ElementKind.Text.name())
				&& element.getDescription() != null
				&& element.getDescription().equals("quick-access"))
			return TeslaFactory.eINSTANCE.createGetQuickAccess();

		// eclipse 3.4 compatibility:
		// EcoreUtil.copy raise exception if argument is null
		return (Command) EcoreUtil.copy(selector);
	}

	public Element elementOf(SelectCommand command) {
		for (CommandToElementEntry entry : scenario.getElementMapping()) {
			if (command.equals(entry.getCommand())) {
				return entry.getElements().get(0);
			}
		}
		// Could not happen because element mapping contains all the selectors
		// that scenario has
		throw new AssertionError();
	}
}
