package de.ugoe.cs.eventbench.windows;

import java.util.LinkedList;
import java.util.List;

import de.ugoe.cs.eventbench.data.Event;
import de.ugoe.cs.eventbench.windows.data.WindowsMessage;
import de.ugoe.cs.eventbench.windowsdefs.MessageDefs;
import de.ugoe.cs.util.console.Console;

public class SequenceSplitter {

	private List<WindowsMessage> currentSequence;
	
	private int openDowns;
	
	private boolean initMessages;
	
	private EventGenerator tokenGenerator;
	
	private List<Event<WindowsMessage>> actionSequence;
	
	public SequenceSplitter() {
		currentSequence = new LinkedList<WindowsMessage>();
		openDowns = 0;
		initMessages = true;
		tokenGenerator = new EventGenerator();
		actionSequence = new LinkedList<Event<WindowsMessage>>();
	}
	
	public void addMessage(WindowsMessage msg) {
		if( startOfSequence(msg) ) {
			if( !initMessages ) {
				Event<WindowsMessage> currentAction = tokenGenerator.generateEvent(currentSequence);
				if( currentAction!=null ) {
					actionSequence.add(currentAction);
				}
				if( isKeyMessage(msg.getType()) && openDowns>0 ) {
					Console.traceln("Key message found with open down mouse messages - will probabably result in a faulty sequence.");
				}
			} else {
				initMessages = false;
			}
			currentSequence = new LinkedList<WindowsMessage>();
		} 
		if( isUpMessage(msg.getType()) ) {
			if( openDowns>0 ) { 
				openDowns--;
			}
		}
		currentSequence.add(msg);
	}
	
	public List<Event<WindowsMessage>> getSequence() {
		return actionSequence;
	}
	
	public void endSession() {
		Event<WindowsMessage> currentAction = tokenGenerator.generateEvent(currentSequence);
		if( currentAction!=null ) {
			actionSequence.add(currentAction);
		}
	}

	private boolean startOfSequence(WindowsMessage msg) {
		boolean isStart = false;
		int msgType = msg.getType();
		if( isKeyMessage(msgType) ) {
			isStart = true;
		}
		if( isDownMessage(msgType) ) {
			openDowns++;
			if( openDowns==1 ) {
				isStart = true;
			}
		}
		if( isDblclkMessage(msgType) ) {
			openDowns++;
		}
		return isStart;
	}

	private boolean isKeyMessage(int msgType) {
		boolean isKeyMsg = false;
		switch (msgType) {
			case MessageDefs.WM_KEYDOWN:
			case MessageDefs.WM_KEYUP:
			case MessageDefs.WM_SYSKEYDOWN:
			case MessageDefs.WM_SYSKEYUP:
				isKeyMsg = true;
				break;
			default:
					break;
		}
		return isKeyMsg;
	}
	
	private boolean isDownMessage(int msgType) {
		boolean isDownMsg = false;
		switch (msgType) {
			case MessageDefs.WM_LBUTTONDOWN:
			case MessageDefs.WM_RBUTTONDOWN:
			case MessageDefs.WM_MBUTTONDOWN:
			case MessageDefs.WM_XBUTTONDOWN:
			case MessageDefs.WM_NCLBUTTONDOWN:
			case MessageDefs.WM_NCRBUTTONDOWN:
			case MessageDefs.WM_NCMBUTTONDOWN:
			case MessageDefs.WM_NCXBUTTONDOWN:
				isDownMsg = true;
				break;
			default:
				break;
		}
		return isDownMsg;
	}

	private boolean isDblclkMessage(int msgType) {
		boolean isDblclkMsg = false;
		switch (msgType) {
			case MessageDefs.WM_LBUTTONDBLCLK:
			case MessageDefs.WM_RBUTTONDBLCLK:
			case MessageDefs.WM_MBUTTONDBLCLK:
			case MessageDefs.WM_XBUTTONDBLCLK:
			case MessageDefs.WM_NCLBUTTONDBLCLK:
			case MessageDefs.WM_NCRBUTTONDBLCLK:
			case MessageDefs.WM_NCMBUTTONDBLCLK:
			case MessageDefs.WM_NCXBUTTONDBLCLK:
				isDblclkMsg = true;
				break;
			default:
				break;
		}
		return isDblclkMsg;
	}
	
	private boolean isUpMessage(int msgType) {
		boolean isUpMsg = false;
		switch (msgType) {
			case MessageDefs.WM_LBUTTONUP:
			case MessageDefs.WM_RBUTTONUP:
			case MessageDefs.WM_MBUTTONUP:
			case MessageDefs.WM_XBUTTONUP:
			case MessageDefs.WM_NCLBUTTONUP:
			case MessageDefs.WM_NCRBUTTONUP:
			case MessageDefs.WM_NCMBUTTONUP:
			case MessageDefs.WM_NCXBUTTONUP:
				isUpMsg = true;
				break;
			default:
				break;
		}
		return isUpMsg;
	}
	
}
