
package de.ugoe.cs.quest.eventcore.gui;

import java.util.List;

import de.ugoe.cs.quest.eventcore.Event;

/**
 * <p>
 * A text input represents a list of key events that together represent entering text into a text
 * field or text area.
 * </p>
 * 
 * @version 1.0
 * @author Patrick Harms, Steffen Herbold
 */
public class TextInput implements IInteraction {

    /**
     * <p>
     * Defines how the {@link TextInput}s are evaluated as equal.
     * </p>
     * 
     * @version 1.0
     * @author Steffen Herbold
     */
    public enum TextEquality {
        /**
         * <p>
         * Two text inputs are equal if their {@link TextInput#textInputEvents} are equal.
         * </p>
         */
        LEXICAL,
        /**
         * <p>
         * Two text inputs are equal if their {@link TextInput#enteredText}s are equal.
         * </p>
         */
        SYNTACTICAL,
        /**
         * <p>
         * All text inputs are equal.
         * </p>
         */
        SEMANTICAL
    };

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

    /**
     * <p>
     * The text resulting from the text input events.
     * </p>
     */
    private String enteredText;

    /**
     * <p>
     * The text input events that caused the entering of the text.
     * </p>
     */
    private List<Event> textInputEvents;

    /**
     * <p>
     * Defines how this TextInput event evaluates the equality.
     * </p>
     */
    private final TextEquality equalityType;

    /**
     * <p>
     * Constructor. Creates a new {@link TextInput} with {@link TextEquality#LEXICAL} equality.
     * </p>
     * 
     * @param enteredText
     *            text resulting from the inputs
     * @param textInputEvents
     *            text input events of which this input consists
     */
    public TextInput(String enteredText, List<Event> textInputEvents) {
        this(enteredText, textInputEvents, TextEquality.LEXICAL);
    }

    /**
     * <p>
     * Constructor. Creates a new {@link TextInput}..
     * </p>
     * 
     * @param enteredText
     *            text resulting from the inputs
     * @param textInputEvents
     *            text input events of which this input consists
     * @param equalityType
     *            defines how this event evaluates the equality (@see {@link TextEquality})
     */
    public TextInput(String enteredText, List<Event> textInputEvents, TextEquality equalityType) {
        this.enteredText = enteredText;
        this.textInputEvents = textInputEvents;
        this.equalityType = equalityType;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.harms.attef.userinteraction.Interaction#getName()
     */
    public String getName() {
        return "TextInput(\"" + enteredText + "\")";
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "text input \"" + enteredText + "\"";
    }

    /**
     * <p>
     * Returns the entered text.
     * </p>
     * 
     * @return the entered text
     */
    public String getEnteredText() {
        return enteredText;
    }

    /**
     * <p>
     * Returns the events of which this {@link TextInput} consists.
     * </p>
     * 
     * @return the textInputEvents
     */
    public List<Event> getTextInputEvents() {
        // TODO should return an immutable view on the list
        return textInputEvents;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.harms.attef.userinteraction.Interaction#startsLogicalSequence()
     */
    public boolean startsLogicalSequence() {
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.harms.attef.userinteraction.Interaction#finishesLogicalSequence()
     */
    public boolean finishesLogicalSequence() {
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        else if (obj instanceof TextInput) {
            switch (equalityType)
            {
                case LEXICAL:
                    return textInputEvents.equals(((TextInput) obj).textInputEvents);
                case SYNTACTICAL:
                    return enteredText.equals(((TextInput) obj).enteredText);
                case SEMANTICAL:
                    return true;
                default:
                    throw new AssertionError("reached source code that should be unreachable");
            }
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        int hashCode = getClass().hashCode();
        if (equalityType == TextEquality.LEXICAL) {
            hashCode += enteredText.hashCode() + textInputEvents.size();
        }
        else if (equalityType == TextEquality.SYNTACTICAL) {
            hashCode += enteredText.hashCode();
        }
        return hashCode;
    }

}
