package scriptbuilder.structures;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import scriptbuilder.gui.ScriptBuilderGuiConstants;
import scriptbuilder.structures.events.ScriptEventInterface;

/**
 * An instance in time in the simulation. Each timeslice has a start time, an X
 * position on the GUI timeline, and a list of ScriptEvents which occur at that
 * time.
 *
 * @author Greg Eddington <geddingt@calpoly.edu>
 * @author Bryan McGuffin
 * @version 2017/06/30
 */
public class TimeSlice implements Comparable
{

    //Events which occur at this instance
    /**
     * List of Script Events which begin at this instance.
     */
    public List<ScriptEventInterface> events;
    //Absolute start time of this time slice
    private int seconds;

    /**
     * Constructor.
     *
     * @param seconds Number of seconds from the beginning of the simulation
     * that this timeslice occurs
     */
    public TimeSlice(int seconds)
    {
        this.seconds = seconds;
        events = new ArrayList<ScriptEventInterface>();
    }

    /**
     * Add a new script event to this time slice. Sort events by event type.
     *
     * @param event the ScriptEvent to be added
     */
    public void addEvent(ScriptEventInterface event)
    {
        events.add(event);
        Collections.sort(events);
    }

    /**
     * Get the X position of this timeslice on the GUI timeline. Affected by
     * zoom level.
     *
     * @return Screen distance from the start of the timeline that this
     * timeslice occurs
     */
    public int getX()
    {
        return seconds / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
                * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
    }

    /**
     * Get the start time of this timeSlice.
     *
     * @return the start time of the timeslice in seconds, from the beginning of
     * the simulation
     */
    public int getTime()
    {
        return seconds;
    }

    /**
     * Shift the start position of this timeslice to the right by some amount.
     *
     * @param amnt the number of seconds forward in time to push this slice
     */
    public void shift(int amnt)
    {
        seconds += amnt;
    }

    /**
     * Get the number of seconds that events which start in this timeslice are
     * active.
     *
     * @return The duration of the longest-lasting event in this slice.
     */
    public int getEffectiveDuration()
    {
        int dur = 0;
        for (ScriptEventInterface e : events)
        {
            if (e.getLength() > dur)
            {
                dur = e.getLength();
            }
        }
        return dur;
    }

    /**
     * Get the text to be displayed when hovering over this timeSlice.
     *
     * @param y the y-position of the cursor on the GUI
     * @return The text to be displayed: all events are listed if we're on the
     * main incident line, but only one event is listed if we're hovering over
     * that particular event
     */
    public String getToolTipText(int y)
    {
        int i = (y - ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_TOP_MARGIN);
        if (i < 0)
        {
            if (i > (-1 * ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP))
            {
                String s = toString();
                if (s.equals(""))
                {
                    return null;
                }

                return "<html>" + s.replace("\n", "<br/>") + "</html>";
            }
            else
            {
                return null;
            }
        }

        i /= ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP;
        if (i < events.size())
        {
            return events.get(i).toString();
        }
        return null;
    }

    /**
     * List all the events attached to this timeslice, with line breaks between.
     *
     * @return A list of the form: event1_type - event1_description event2_type
     * - event2_description ...
     */
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();

        for (ScriptEventInterface event : events)
        {
            sb.append(event.toString());
            sb.append('\n');
        }

        return sb.toString();
    }

    /**
     * Order the timeslices by start time. Earlier start times come first.
     *
     * @param o the other timeSlice to be compared
     * @return -1, 0 , or 1 depending on if this timeSlice comes before,
     * simultaneously, or after the other
     */
    @Override
    public int compareTo(Object o)
    {
        TimeSlice other = (TimeSlice) o;
        if (this.getTime() < other.getTime())
        {
            return -1;
        }
        else if (this.getTime() > other.getTime())
        {
            return 1;
        }
        else
        {
            return 0;
        }

    }
}
