//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

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

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

import de.ugoe.cs.autoquest.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;
        
        if (this.enteredText == null) {
            this.enteredText = "";
        }
        
        if (this.textInputEvents == null) {
            this.textInputEvents = new LinkedList<Event>();
        }
    }

    /*
     * (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. The returned list is immutable.
     * </p>
     * 
     * @return the textInputEvents
     */
    public List<Event> getTextInputEvents() {
        return Collections.unmodifiableList(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;
    }

}
