package de.ugoe.cs.quest.plugin.mfc.eventcore;

import de.ugoe.cs.quest.IReplayDecorator;
import de.ugoe.cs.quest.eventcore.IReplayable;
import de.ugoe.cs.quest.plugin.mfc.MFCReplayDecorator;
import de.ugoe.cs.util.StringTools;

/**
 * <p>
 * Contains all informations about a windows message, i.e., all parameters that are read when a
 * windows message is parsed as well as its target, hwnd, etc.
 * </p>
 * 
 * @author Steffen Herbold
 * @version 1.0
 * 
 */
public class ReplayWindowsMessage extends WindowsMessage implements IReplayable {

    /**
     * <p>
     * Id for object serialization.
     * </p>
     */
    private static final long serialVersionUID = 1L;

    /**
     * <p>
     * If the LPARAM contains a HWND, this string stores the target of the HWND.
     * </p>
     */
    private String LPARAMasWindowDesc = null;

    /**
     * <p>
     * If the WPARAM contains a HWND, this string stores the target of the HWND.
     * </p>
     */
    private String WPARAMasWindowDesc = null;

    /**
     * <p>
     * Delay after sending the messages during a replay. Default: 0
     * </p>
     */
    private int delay = 0;

    /**
     * <p>
     * Constructor. Creates a new replay message with a given {@link WindowsMessage}.
     * </p>
     * 
     * @param replayedMessage
     *            message from which the replay is generated
     */
    public ReplayWindowsMessage(WindowsMessage replayedMessage)
    {
        super(replayedMessage.getType(),
              replayedMessage.getTarget(),
              replayedMessage.getParameters());
        
        // the target may have changed in the meantime. So reset the targetXML to the one stored
        // with the provided message
        if (!super.getTargetXML().equals(replayedMessage.getTargetXML())) {
            setTargetXML(replayedMessage.getTargetXML());
        }
    }

    /**
     * <p>
     * Constructor. Creates a new message with a given message type.
     * </p>
     * 
     * @param type
     *            type of the message
     */
    public ReplayWindowsMessage(WindowsMessageType type)
    {
        super(type);
    }

    /**
     * <p>
     * Two {@link ReplayWindowsMessage} are equal, if their {@link #type}, {@link #getTargetXML},
     * and {@link #params} are equal.
     * </p>
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        boolean isEqual = false;
        if (other instanceof ReplayWindowsMessage) {
            isEqual = super.equals(other);
        }
        return isEqual;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return super.hashCode();
    }

    /**
     * <p>
     * Returns a string representation of the message of the form "msg[target=HWND;type=TYPE]".
     * </p>
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "msg[target=" + getParameter("window.hwnd") + ";type=" + type + "]";
    }

    /**
     * <p>
     * Sets the LPARAM of a message.
     * </p>
     * 
     * @param paramValue
     *            value of the LPARAM
     */
    public void setLPARAM(long paramValue) {
        super.addParameter("LPARAM", paramValue);
    }

    /**
     * <p>
     * Sets the WPARAM of a message.
     * </p>
     * 
     * @param paramValue
     *            value of the WPARAM
     */
    public void setWPARAM(long paramValue) {
        super.addParameter("WPARAM", paramValue);
    }

    /**
     * <p>
     * If the LPARAM contains a HWND, this function can be used to set a target string to identify
     * the HWND at run-time.
     * </p>
     * 
     * @param windowDesc
     *            target string
     */
    public void setLPARAMasWindowDesc(String windowDesc) {
        LPARAMasWindowDesc = windowDesc;
    }

    /**
     * <p>
     * If the WPARAM contains a HWND, this function can be used to set a target string to identify
     * the HWND at run-time.
     * </p>
     * 
     * @param windowDesc
     *            target string
     */
    public void setWPARAMasWindowDesc(String windowDesc) {
        WPARAMasWindowDesc = windowDesc;
    }

    /**
     * <p>
     * If the LPARAM contains a HWND and the target string for the HWND is set, this function
     * returns the target string. Otherwise, {@code null} is returned.
     * </p>
     * 
     * @return target string if available; {@code null} otherwise
     */
    public String getLPARAMasWindowDesc() {
        return LPARAMasWindowDesc;
    }

    /**
     * <p>
     * If the WPARAM contains a HWND and the target string for the HWND is set, this function
     * returns the target string. Otherwise, {@code null} is returned.
     * </p>
     * 
     * @return target string if available; {@code null} otherwise
     */
    public String getWPARAMasWindowDesc() {
        return WPARAMasWindowDesc;
    }

    /**
     * <p>
     * Sets the XML target string.
     * </p>
     *
     * @param targetXML the target string
     */
    public void setTargetXML(String targetXML) {
        this.targetXML = targetXML;
    }

    /**
     * <p>
     * Returns the delay after this message during replays.
     * </p>
     * 
     * @return delay after this message
     */
    public int getDelay() {
        return delay;
    }

    /**
     * <p>
     * Sets the delay after this message during replays.
     * </p>
     * 
     * @param delay
     *            delay after this message
     */
    public void setDelay(int delay) {
        this.delay = delay;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.quest.eventcore.IReplayable#getReplay()
     */
    @Override
    public String getReplay() {
        StringBuilder currentMsgStr = new StringBuilder(400);
        currentMsgStr.append("  <msg type=\"" + type.getNumber() + "\" ");
        currentMsgStr.append("LPARAM=\"" + super.getLPARAM() + "\" ");
        currentMsgStr.append("WPARAM=\"" + super.getWPARAM() + "\" ");
        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(super.getTargetXML());
        currentMsgStr.append(StringTools.ENDLINE);
        currentMsgStr.append("  </msg>");
        currentMsgStr.append(StringTools.ENDLINE);
        return currentMsgStr.toString();
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.quest.eventcore.IReplayable#getDecorator()
     */
    @Override
    public IReplayDecorator getDecorator() {
        return MFCReplayDecorator.getInstance();
    }

}
