package de.ugoe.cs.eventbench.windows.data;

import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.Map;

import de.ugoe.cs.eventbench.data.IReplayable;
import de.ugoe.cs.util.StringTools;

public class WindowsMessage implements IReplayable {
	/**
	 * Id for object serialization. 
	 */
	private static final long serialVersionUID = 1L;
	
	final int type;
	private String windowClass = "";
	private int resourceId = 0;
	private String xmlWindowDescription = "";
	private String parentNames = null;
	private String parentClass = null;

	private long LPARAM = 0;
	private long WPARAM = 0;

	private String LPARAMasWindowDesc = null;
	private String WPARAMasWindowDesc = null;

	private int delay = 0;
	
	private Map<String, String> params = new HashMap<String, String>();

	public WindowsMessage(int type) {
		this.type = type;
	}

	public void addParameter(String type, String value) {
		params.put(type, value);
		if (type.equals("LPARAM")) {
			LPARAM = Long.parseLong(value);
		} else if (type.equals("WPARAM")) {
			WPARAM = Long.parseLong(value);
		}
	}

	public int getType() {
		return type;
	}

	public String getParameter(String type) {
		return params.get(type);
	}

	public String getWindowClass() {
		return windowClass;
	}

	public int getHwnd() {
		int hwnd = -1;
		String hwndString = getParameter("window.hwnd"); // possible, as
															// "window.hwnd" is
															// mandatory
		if (hwndString != null) {
			hwnd = Integer.parseInt(hwndString);
		}
		return hwnd;
	}

	public int getWindowResourceId() {
		return resourceId;
	}

	@Override
	public boolean equals(Object other) {
		if( other==this) {
			return true;
		}
		boolean isEqual = false;
		if (other instanceof WindowsMessage) {
			isEqual = ((WindowsMessage) other).type == this.type
					&& ((WindowsMessage) other).xmlWindowDescription
							.equals(this.xmlWindowDescription)
					&& ((WindowsMessage) other).params.equals(this.params);
		}
		return isEqual;
	}

	@Override
	public int hashCode() {
		int multiplier = 17;
		int hash = 42;

		hash = multiplier * hash + type;
		hash = multiplier * hash + xmlWindowDescription.hashCode();
		hash = multiplier * hash + params.hashCode();

		return hash;
	}

	@Override
	public String toString() {
		return "msg[target=" + getParameter("window.hwnd") + ";type=" + type
				+ "]";
	}

	public void setTarget(WindowTree windowTree)
			throws InvalidParameterException {
		int hwnd = Integer.parseInt(getParameter("window.hwnd"));
		WindowTreeNode node = windowTree.find(hwnd);
		if (node == null) {
			throw new InvalidParameterException("No window with HWND " + hwnd
					+ " found in window tree!");
		} else {
			windowClass = node.getClassName();
			resourceId = node.getResourceId();
			xmlWindowDescription = node.xmlRepresentation();
			parentNames = node.getParentNames();
			WindowTreeNode parent = node.getParent();
			if( parent==null ) {
				parentClass = "";
			} else {
				parentClass = parent.getClassName();
			}
		}
	}

	public void setLPARAM(long paramValue) {
		LPARAM = paramValue;
	}

	public void setWPARAM(long paramValue) {
		WPARAM = paramValue;
	}

	public long getLPARAM() {
		return LPARAM;
	}

	public long getWPARAM() {
		return WPARAM;
	}

	public void setLPARAMasWindowDesc(String windowDesc) {
		LPARAMasWindowDesc = windowDesc;
	}

	public void setWPARAMasWindowDesc(String windowDesc) {
		WPARAMasWindowDesc = windowDesc;
	}

	public String getLPARAMasWindowDesc() {
		return LPARAMasWindowDesc;
	}

	public String getWPARAMasWindowDesc() {
		return WPARAMasWindowDesc;
	}

	public String getXmlWindowDescription() {
		return xmlWindowDescription;
	}

	public void setXmlWindowDescription(String xmlWindowDescription) {
		this.xmlWindowDescription = xmlWindowDescription;
	}

	public int getDelay() {
		return delay;
	}

	public void setDelay(int delay) {
		this.delay = delay;
	}

	public String getParentNames() {
		return parentNames;
	}
	
	public String getParentClass() {
		return parentClass;
	}

	public int getNumParams() {
		return params.size();
	}
	
	public String getReplay() {
		StringBuilder currentMsgStr = new StringBuilder(400);
		currentMsgStr.append("  <msg type=\""+type+"\" ");
		currentMsgStr.append("LPARAM=\""+LPARAM+"\" ");
		currentMsgStr.append("WPARAM=\""+WPARAM+"\" ");
		currentMsgStr.append("delay=\""+delay+"\">");
		if( LPARAMasWindowDesc!=null ) {
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append("   <LPARAM>");
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append(LPARAMasWindowDesc);
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append("</LPARAM>");
		} 
		if( WPARAMasWindowDesc!=null ) {
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append("   <WPARAM>");
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append(WPARAMasWindowDesc);
			currentMsgStr.append(StringTools.ENDLINE);
			currentMsgStr.append("   </WPARAM>");
		}
		currentMsgStr.append(StringTools.ENDLINE);
		currentMsgStr.append(xmlWindowDescription);
		currentMsgStr.append(StringTools.ENDLINE);
		currentMsgStr.append("  </msg>");
		currentMsgStr.append(StringTools.ENDLINE);
		return currentMsgStr.toString();
	}
	
	public String getTarget() {
		return xmlWindowDescription;
	}
}
