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

import java.util.ArrayList;
import java.util.List;

import de.ugoe.cs.util.StringTools;

/**
 * <p>
 * This class implements a node in the {@link WindowTree} that is maintained
 * during parsing a session.
 * </p>
 * <p>
 * The window tree is structure that contains the hierarchy of the windows of a
 * application as well as basic information about each window: the hwnd; its
 * name; its resource id; its class name.
 * </p>
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class WindowTreeNode {

	/**
	 * <p>
	 * Name of the window. May change over time.
	 * </p>
	 */
	private String windowName;

	/**
	 * <p>
	 * Handle of the window. Used as unique identifier during its existence.
	 * </p>
	 */
	private final int hwnd;

	/**
	 * <p>
	 * Resource id of the window.
	 * </p>
	 */
	private final int resourceId;

	/**
	 * <p>
	 * Class name of the window.
	 * </p>
	 */
	private final String className;

	/**
	 * <p>
	 * True, if the window is modal.
	 * </p>
	 */
	private final boolean isModal;

	/**
	 * <p>
	 * Parent of the window. <code>null</code> if the window has no parent.
	 * </p>
	 */
	private WindowTreeNode parent;

	/**
	 * <p>
	 * List of the windows children. May be empty.
	 * </p>
	 */
	private List<WindowTreeNode> children;

	/**
	 * <p>
	 * Creates a new WindowTreeNode.
	 * </p>
	 * <p>
	 * The constructor is protected WindowTreeNode may only be created from the
	 * WindowTree.
	 * </p>
	 * 
	 * @param hwnd
	 *            hwnd of the window
	 * @param parent
	 *            reference to the parent's WindowTreeNode
	 * @param windowName
	 *            name of the window
	 * @param resourceId
	 *            resource id of the window
	 * @param className
	 *            class name of the window
	 * @param isModal
	 *            modality of the window
	 */
	protected WindowTreeNode(int hwnd, WindowTreeNode parent,
			String windowName, int resourceId, String className, boolean isModal) {
		this.hwnd = hwnd;
		this.parent = parent;
		this.windowName = windowName;
		this.resourceId = resourceId;
		this.className = className;
		this.isModal = isModal;
		children = new ArrayList<WindowTreeNode>();
	}

	/**
	 * <p>
	 * Returns a reference to the WindowTreeNode of the parent.
	 * </p>
	 * 
	 * @return WindowTreeNode of the parent
	 */
	public WindowTreeNode getParent() {
		return parent;
	}

	/**
	 * <p>
	 * Returns the list of the windows children.
	 * </p>
	 * 
	 * @return list of the windows children
	 */
	public List<WindowTreeNode> getChildren() {
		return children;
	}

	/**
	 * <p>
	 * Returns the name of the window.
	 * </p>
	 * 
	 * @return name of the window
	 */
	public String getName() {
		return windowName;
	}

	/**
	 * <p>
	 * Returns the hwnd of the window.
	 * </p>
	 * 
	 * @return hwnd of the window
	 */
	public int getHwnd() {
		return hwnd;
	}

	/**
	 * <p>
	 * Returns the resource id of the window.
	 * </p>
	 * 
	 * @return resource id of the window
	 */
	public int getResourceId() {
		return resourceId;
	}

	/**
	 * <p>
	 * Returns the class name of the window.
	 * </p>
	 * 
	 * @return class name of the window
	 */
	public String getClassName() {
		return className;
	}

	/**
	 * <p>
	 * Sets the name of the window.
	 * </p>
	 * 
	 * @param text
	 *            new name of the window
	 */
	public void setName(String text) {
		windowName = text;
	}

	/**
	 * <p>
	 * Removes a the window and all its children from the {@link WindowTree}.
	 * </p>
	 * 
	 * @return list of the children of the window for further clean up.
	 */
	public List<WindowTreeNode> remove() {
		if (parent != null) {
			parent.removeChild(this);
		}
		return children;
	}

	/**
	 * <p>
	 * Removes a child window.
	 * </p>
	 * 
	 * @param child
	 *            reference to the child window to be removed
	 */
	public void removeChild(WindowTreeNode child) {
		children.remove(child);
	}

	/**
	 * <p>
	 * Adds a new child window and creates WindowTreeNode for it.
	 * </p>
	 * 
	 * @param childHwnd
	 *            hwnd of the child window
	 * @param childWindowName
	 *            name of the child window
	 * @param resourceId
	 *            resource id of the child window
	 * @param className
	 *            class name of the child window
	 * @param isModal
	 *            modality of the child window
	 * @return reference to the WindowTreeNode created for the child window
	 */
	public WindowTreeNode addChild(int childHwnd, String childWindowName,
			int resourceId, String className, boolean isModal) {
		WindowTreeNode child = new WindowTreeNode(childHwnd, this,
				childWindowName, resourceId, className, isModal);
		children.add(child);
		return child;
	}

	/**
	 * <p>
	 * Returns a string identfier of the window:<br>
	 * {@code [resourceId;"windowName";"className";modality]}
	 * </p>
	 * 
	 * @return identifier string of the window
	 */
	@Override
	public String toString() {
		return "[" + resourceId + ";\"" + windowName + "\";\"" + className
				+ "\";" + isModal + "]";
	}

	/**
	 * <p>
	 * Returns an XML representation of the window, including its parents. It is
	 * defined as follows:<br>
	 * <code>
	 * parent#xmlRepresentation()<br>
	 * &lt;window name="this.windowname" class="this.className" resourceId="this.resourceId" isModal="this.isModel"/&gt;
	 * </code>
	 * </p>
	 * 
	 * @return xml representation of the window
	 */
	public String xmlRepresentation() {
		String xmlString = "";
		if (parent != null) {
			xmlString = parent.xmlRepresentation();
		}
		xmlString += "<window name=\""
				+ StringTools.xmlEntityReplacement(windowName) + "\" class=\""
				+ StringTools.xmlEntityReplacement(className)
				+ "\" resourceId=\"" + resourceId + "\" isModal=\"" + isModal
				+ "\"/>";
		return xmlString;
	}

	/**
	 * <p>
	 * Returns the names of the parents and itself separated by dots, e.g.,
	 * "GrandParent.Parent.windowName"
	 * </p>
	 * 
	 * @return names of the parents separated by dots
	 */
	public String getParentNames() {
		String parentNames = "";
		if (parent != null) {
			parentNames = parent.getParentNames() + ".";
		}
		parentNames += windowName;
		return parentNames;
	}

}
