package scriptbuilder.gui.panels;

import event.editor.Editor;
import event.editor.Properties;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;
import scriptbuilder.gui.ScriptBuilderFrame;
import scriptbuilder.gui.ScriptBuilderGuiConstants;
import scriptbuilder.gui.drawers.CursorDrawer;
import scriptbuilder.gui.drawers.EventIconDrawer;
import scriptbuilder.gui.drawers.IncidentTimelineDrawer;
import scriptbuilder.structures.ScriptEvent;
import scriptbuilder.structures.ScriptEvent.ScriptEventType;
import scriptbuilder.structures.ScriptIncident;
import scriptbuilder.structures.TimeSlice;

/**
 *
 * @author Greg Eddington <geddingt@calpoly.edu>
 */
public class IncidentTimelinePanel extends JPanel
{
    ScriptIncident incident;
    boolean collapsed;
    boolean visible;
    boolean focused;
    int cursorTime, lastSlice, x, y;
    Map<ScriptEventType, Properties> eventTypeToPropertyMap;

    public class IncidentTimelineMouseListener extends MouseInputAdapter
    {
        @Override
        public void mouseEntered(MouseEvent e)
        {
            incident.setIncidentActive();
            focused = true;
        }

        @Override
        public void mouseExited(MouseEvent e)
        {
            focused = false;
            repaint();
        }

        @Override
        public void mouseClicked(MouseEvent e)
        {
            Editor ed = new Editor();
            ScriptBuilderFrame f = (ScriptBuilderFrame)getTopLevelAncestor();

            x = cursorTime = e.getX();
            y = e.getY();

            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK >
                    ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
            {
                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK -
                        e.getX() %
                        ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
            }
            else
            {
                cursorTime -= e.getX() %
                    ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
            }

            int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK) -
                           (incident.offset / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION);

            /** Check if click is out of bounds **/
            if (!(newSlice < incident.slices.size() && newSlice >= 0) || incident == null)
            {
                return;
            }

            for (ScriptEvent se : incident.slices.get(newSlice).events)
            {
                ed.addProperty(eventTypeToPropertyMap.get(se.getScriptEventType()));
            }
            
            /** Add a new icon if left mouse button was clicked **/
            if (e.getButton() == MouseEvent.BUTTON1)
            {
                if (f.currentEventType != null)
                {
                    ed.addProperty(eventTypeToPropertyMap.get(f.currentEventType));
                    incident.slices.get(newSlice).addEvent(new ScriptEvent(f.currentEventType));
                    f.update(f.getScript(), f.getScript());
                }
            }

            ed.setVisible(true);
        }

        @Override
        public void mouseMoved(MouseEvent e)
        {
            x = cursorTime = e.getX();
            y = e.getY();

            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK >
                    ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
            {
                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK -
                        e.getX() %
                        ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
            }
            else
            {
                cursorTime -= e.getX() %
                    ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
            }


            if (incident != null)
            {
                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK) -
                        (incident.offset / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION);
                if (newSlice < incident.slices.size() && newSlice >= 0)
                {
                    incident.setSliceActive(newSlice);
                    lastSlice = newSlice;
                    String newToolTip;
                    if (collapsed)
                        newToolTip = incident.slices.get(newSlice).toString();
                    else
                        newToolTip = incident.slices.get(newSlice).getToolTipText(y);
                    setToolTipText((newToolTip == null || newToolTip.equals(""))
                            ? null : newToolTip);
                }
            }
            
            repaint();
        }
    }

    public IncidentTimelinePanel()
    {
        super();

//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT

        eventTypeToPropertyMap = new HashMap();
        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);

        // Add the mouse listener
        IncidentTimelineMouseListener mouseListener =
                new IncidentTimelineMouseListener();
        addMouseMotionListener(mouseListener);
        addMouseListener(mouseListener);
    }

    public void update(ScriptIncident incident)
    {
        this.incident = incident;
        if (incident != null)
            this.collapsed = incident.collapsed;
        this.visible = incident != null;

        Dimension newSize;
        if (visible)
        {
            if (collapsed)
            {
                newSize = new Dimension((incident.length + incident.offset) /
                        ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION *
                        ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT);
            }
            else
            {
                int mostEvents = 0;
                for (TimeSlice slice : incident.slices)
                {
                    if (slice.events.size() > mostEvents)
                        mostEvents = slice.events.size();
                }

                newSize = new Dimension((incident.length + incident.offset) /
                        ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION *
                        ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT +
                        ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * (mostEvents + 1));
            }
        }
        else
        {
            newSize = new Dimension(0, 0);
        }
        this.setSize(newSize);
        this.setPreferredSize(newSize);

        invalidate();
    }

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);

        if (!visible)
            return;

        Graphics2D g2d = (Graphics2D)g;
        IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, collapsed);

        if (focused)
        {
            CursorDrawer.DrawCursor(g2d, cursorTime, false);
            if (((ScriptBuilderFrame)this.getTopLevelAncestor()).currentEventType != null)
                EventIconDrawer.DrawEventIcon(g2d,
                    ((ScriptBuilderFrame)this.getTopLevelAncestor()).currentEventType,
                    x+5, y+10);
        }
    }
}
