package scriptbuilder.structures;

import java.util.Observable;
import scriptbuilder.structures.events.*;

/**
 * A single script event. It has an event type, and a duration (in seconds) of
 * at least 1. It is comparable based on event type.
 *
 * @author Greg Eddington <geddingt@calpoly.edu>
 * @author Bryan McGuffin
 * @version 2017/06/30
 */
public abstract class ScriptEvent extends Observable implements I_ScriptEvent
{

    /**
     * Compare the Script Events based on their type enum.
     *
     * @param a the other script event to be compared
     * @return -1, 0, or 1 depending on if this event's type comes before,
     * simultaneously, or after the other event's type in the enum list
     */
    @Override
    public int compareTo(Object a)
    {
        ScriptEvent o = (ScriptEvent) a;
        return this.type.compareTo(o.type);
    }

    @Override
    public int getLength()
    {
        return length;
    }

    /**
     * The different possible event types, ordered by event domain and then
     * alphabetically. The string parameter of each type is the name of a .png
     * image which will be used as an icon to represent that event type.
     */
    public static enum ScriptEventType
    {

        CAD_EVENT("CAD"),
        UNIT_EVENT("Unit"),
        TOW_EVENT("Tow"),
        WITNESS_EVENT("Witness"),
        AUDIO_EVENT("Audio"),
        CCTV_EVENT("CCTV"),
        CHP_RADIO_EVENT("CHPRadio"),
        PARAMICS_EVENT("Paramics"),
        TELEPHONE_EVENT("Telephone"),
        CAD_EVAL_EVENT("CADEval"),
        ATMS_EVAL_EVENT("ATMSEval"),
        CMS_EVAL_EVENT("CMSEval"),
        ACTIVITY_LOG_EVAL_EVENT("ActivityLogEval"),
        FACILITATOR_EVAL_EVENT("FacilitatorEval"),
        RADIO_EVAL_EVENT("RadioEval"),
        MAINTENANCE_RADIO_EVENT("MaintenanceRadio"),
        TMT_RADIO_EVENT("TMTRadio");

        /**
         * The file name of a PNG image to be used as the icon for this event
         * type.
         */
        public String IMAGE_NAME;

        private ScriptEventType(String image)
        {
            this.IMAGE_NAME = image;
        }
    }

    /**
     * The Event type, from the enum of ScriptEventType.
     */
    private ScriptEventType type;

    /**
     * Number of seconds this event lasts
     */
    public int length;
    
    private TimeSlice slice;

    /**
     * Constructor with type and length parameters.
     *
     * @param type The type of event.
     * @param l the duration of the event in seconds.
     */
    public ScriptEvent(ScriptEventType type, int l)
    {
        this.type = type;
        this.length = l;
    }

    /**
     * Constructor with no length parameter. Event length will default to 1
     * second.
     *
     * @param type The type of event.
     */
    public ScriptEvent(ScriptEventType type)
    {
        this.type = type;
        this.length = 1;
    }

    /**
     * Get the event type of this ScriptEvent.
     *
     * @return The enum type of the event
     */
    public ScriptEventType getScriptEventType()
    {
        return type;
    }

    /**
     * Get the string representation of this event. This string will be used in
     * the tooltip text when the user hover the mouse over this event.
     *
     * @return A string containing this event's type, and a STUB where its
     * description will go later.
     */
    @Override
    public String toString()
    {
        return this.type.toString() + " - [Event Description]";
    }

    /**
     * Generate a new script event object of the specified type.
     *
     * @param t the type of the script event
     * @return a new I_ScriptEvent object matching the given type
     */
    public static I_ScriptEvent factoryByType(ScriptEventType t)
    {
        switch (t)
        {
            case AUDIO_EVENT:
                return new AudioEvent();
            case CAD_EVENT:
                return new CADEvent();
            case CCTV_EVENT:
                return new CCTVEvent();
            case CHP_RADIO_EVENT:
                return new CHPRadioEvent();
            case PARAMICS_EVENT:
                return new ParamicsEvent();
            case TOW_EVENT:
                return new TowEvent();
            case UNIT_EVENT:
                return new UnitEvent();
            case WITNESS_EVENT:
                return new WitnessEvent();
            case MAINTENANCE_RADIO_EVENT:
                return new MaintenanceRadioEvent();
            case TMT_RADIO_EVENT:
                return new TMTRadioEvent();
            case TELEPHONE_EVENT:
                return new TelephoneEvent();
            case ATMS_EVAL_EVENT:
                return new ATMSEvaluationEvent();
            case ACTIVITY_LOG_EVAL_EVENT:
                return new ActivityLogEvaluationEvent();
            case CAD_EVAL_EVENT:
                return new CADEvaluationEvent();
            case CMS_EVAL_EVENT:
                return new CMSEvaluationEvent();
            case FACILITATOR_EVAL_EVENT:
                return new FacilitatorEvaluationEvent();
            case RADIO_EVAL_EVENT:
                return new RadioEvaluationEvent();
            default:
                return new TelephoneEvent();
        }
    }

    /**
     * Determines if the event in question is an evaluation event.
     *
     * @param event the event to be checked
     * @return true if the event implements I_EvaluationEvent
     */
    public static boolean isEvaluationEvent(I_ScriptEvent event)
    {
        return event instanceof I_EvaluationEvent;
    }
    
    @Override
    public void removeThis()
    {
        this.slice.events.remove(this);
        this.slice.checkEmpty();
    }
    
    @Override
    public void assignTimeSlice(TimeSlice ts)
    {
        this.slice = ts;
    }
}
