package com.ht.svg.action;

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

import javafx.application.Platform;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;

import com.ht.data.RealTimeDataManager;
import com.ht.svg.AbstractSVGHandler;
import com.ht.ui.svg.SVGViewer;

/**
 * the class handling the actions that can be found over canvases or other
 * components
 * 
 * @author 薄成文
 */
public class ActionsHandler extends AbstractSVGHandler {

	private static final Logger log = Logger.getLogger(ActionsHandler.class
			.getName());
	private List<AbstractActionListener> actions = new ArrayList<AbstractActionListener>();
	private final Map<Element, List<AbstractActionListener>> elementToActions = new HashMap<Element, List<AbstractActionListener>>();
	private final EventListener eventsListener = new SVGEventListener();
	private SVGViewer svgViewer;

	/**
	 * the constructor of the class
	 * 
	 * @param document
	 */
	public ActionsHandler(SVGViewer viewer, Document document) {
		log.config("解析SVG动作.");

		this.svgViewer = viewer;

		NodeList elems = document.getElementsByTagName("simpleSendCommand");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new SimpleSendCommand(
					(Element) elems.item(i));
			actions.add(action);
		}

		elems = document.getElementsByTagName("sendCommand");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new SendCommand(
					(Element) elems.item(i));
			actions.add(action);
		}
		elems = document.getElementsByTagName("sendMeasure");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new SendMeasure(
					(Element) elems.item(i));
			actions.add(action);
		}
		elems = document.getElementsByTagName("showMenu");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new ShowMenuAction(
					(Element) elems.item(i));
			actions.add(action);
		}
		elems = document.getElementsByTagName("blinkingReset");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new BlinkingResetAction(
					(Element) elems.item(i));
			actions.add(action);
		}
		elems = document.getElementsByTagName("ExecuteScript");
		for (int i = 0; i < elems.getLength(); i++) {
			AbstractActionListener action = new RunScript(
					(Element) elems.item(i));
			actions.add(action);
		}
	}

	@Override
	public void init() {
		log.config("初始化并注册SVG动作");
		regist();
	}

	@Override
	public void regist() {
		// adding the actions
		for (AbstractActionListener action : actions) {

			registAction(action);
		}
	}

	@Override
	public void unregist() {
		// removing the actions
		for (AbstractActionListener action : actions) {

			unregistAction(action);
		}

	}

	@Override
	public void dispose() {
		log.config("注销SVG动作");
		// unregist();
		// disposing the actions
		for (AbstractActionListener action : actions) {

			action.dispose();
		}
		actions.clear();
	}

	/**
	 * adds a new action to handle
	 * 
	 * @param action
	 *            an action
	 */
	private void registAction(final AbstractActionListener action) {

		if (action != null) {

			RealTimeDataManager.INSTANCE.registDataChangeListener(action);

			synchronized (elementToActions) {

				final Element actionObject = action.getParentElement();

				List<AbstractActionListener> list = elementToActions
						.get(actionObject);
				if (list == null) {// 首次为该元素注册动作
					list = new ArrayList<AbstractActionListener>();
					elementToActions.put(actionObject, list);

					Platform.runLater(new Runnable() {
						public void run() {
							action.getParentElement().setAttribute("cursor", "pointer");
						}
					});
				}
				list.add(action);
				
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						EventTarget target = (EventTarget) actionObject;
						target.addEventListener(action.getEventType(), eventsListener, false);
					}
				});

			}
		}
	}

	/**
	 * removes the given action from the handler
	 * 
	 * @param action
	 *            an action
	 */
	private void unregistAction(AbstractActionListener action) {

		if (action != null) {

			RealTimeDataManager.INSTANCE.unregistDataChangeListener(action);

			synchronized (elementToActions) {

				Element actionObject = action.getParentElement();
				List<AbstractActionListener> list = elementToActions
						.get(actionObject);
				if (list != null) {
					list.remove(action);
					if (list.isEmpty()) {
						elementToActions.remove(actionObject);
					}
				}
				EventTarget target = (EventTarget) actionObject;
				target.removeEventListener(action.getEventType(),
						eventsListener, false);
			}
		}
	}

	public SVGViewer getSvgViewer() {
		return svgViewer;
	}

	public class SVGEventListener implements EventListener {

		@Override
		public void handleEvent(Event evt) {

			synchronized (elementToActions) {

				Element element = (Element) evt.getTarget();
				List<AbstractActionListener> actionList = elementToActions
						.get(element);

				while (actionList == null) {// 向上查找关联的动作元素
					if (element.getParentNode() == null) {
						break;
					}
					if (element.getParentNode() instanceof Element) {
						element = (Element) element.getParentNode();
						actionList = elementToActions.get(element);
					} else {
						break;
					}
				}

				if (actionList != null) {

					for (AbstractActionListener action : actionList) {
						if (action.getEventType().equals(evt.getType())) {// 触发事件
							action.performAction(evt);
							// MouseEvent e = (MouseEvent) evt;
						}
					}
				}
			}

		}// @method handleEvent
	}
	// end
}
