package tmcsim.highwaymodel;

import tmcsim.highwaymodel.Highways;
import tmcsim.highwaymodel.TrafficEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import tmcsim.cadsimulator.managers.TrafficModelManager;
import tmcsim.common.SimulationException;

/**
 * Read and process all Traffic Events in a file and show
 * resulting highway network. 
 * A snapshot of the highway model after each event is saved in a buffer
 * and a graphical display allows the user to scroll through the history. 
 * This application is used by Traffic Event authors to assist
 * in verifying the correctness of their data file.
 * @author jdalbey
 */
public class TrafficEventsAnimator extends javax.swing.JPanel
{
    /**
     * Error logger.
     */
    private final static Logger logger = Logger.getLogger("trafficmodeleventdriver");

    /**
     * Highways in traffic network
     */
    final private Highways highways;

    /**
     * LinkedList of batch events
     */
    private final LinkedList<TrafficEvent> eventQueue;
    /**
     * Highway history
     */
    private List<String> history;
    /**
     * name of events file obtained from properties
     */
    private String events_file = ""; 
    /**
     * Creates the JPanel and builds the highways and events. 
     */
    public TrafficEventsAnimator() throws RemoteException, SimulationException
    {
        initComponents();

        // Initialize the highway model
        highways = new Highways(
                "config/vds_data/postmile_coordinates.txt");
        final String CONFIG_FILE_NAME = "traffic_model_config.properties";
        String propertiesFile = "config" + System.getProperty("file.separator") 
                 + "traffic_model_config" + System.getProperty("file.separator")  + CONFIG_FILE_NAME;
        Properties props = TrafficModelManager.loadProperties(propertiesFile);
        events_file = props.getProperty("Events_File");
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(events_file);
        } catch (FileNotFoundException ex)
        {
            Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, 
                    "Missing Traffic Events file " + events_file);
            System.exit(-1);
        }
        Scanner fileScanner = new Scanner(fis);        
        // Read all lines from the file of events and put in a queue
        eventQueue = TrafficModelManager.readBatchFile(fileScanner);
    }
    /** Load the traffic events into a history buffer.  This  */
    public void load()
    {
        txtDisplay.setText("Loading traffic events from: " + events_file);
        history = new ArrayList<String>();
        // If we have any events left to process
        while (!eventQueue.isEmpty())
        {
            // Get next event
            TrafficEvent nextEvent = eventQueue.peek();
            System.out.println(nextEvent.eventTime);
            // apply colorization to highways
            highways.applyColorToHighwayStretch(nextEvent.routeNumber, nextEvent.dir,
                    nextEvent.postmile, nextEvent.range, nextEvent.color);
            // get the highwys as a string and add to the history list
            history.add(highways.toString()+"\n"+nextEvent.eventTime);
            // Remove this event from the queue, we're done with it.
            eventQueue.remove();
        }
        scrollBar.setMaximum(history.size());
        // display the first item from the history
        txtDisplay.setText(history.get(0));
    }
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scrollBar = new javax.swing.JScrollBar();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtDisplay = new javax.swing.JTextArea();

        scrollBar.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
            public void adjustmentValueChanged(java.awt.event.AdjustmentEvent evt) {
                scrollbarValueChanged(evt);
            }
        });

        txtDisplay.setColumns(20);
        txtDisplay.setFont(new java.awt.Font("Courier New", 0, 15)); // NOI18N
        txtDisplay.setRows(5);
        jScrollPane1.setViewportView(txtDisplay);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(scrollBar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 388, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
            .addComponent(scrollBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void scrollbarValueChanged(java.awt.event.AdjustmentEvent evt)//GEN-FIRST:event_scrollbarValueChanged
    {//GEN-HEADEREND:event_scrollbarValueChanged
        // when the scroll bar is moved show the corresponding snapshot from history
        txtDisplay.setText(history.get(evt.getValue()) );
        repaint();
    }//GEN-LAST:event_scrollbarValueChanged

    /** Entry point for the application.  Builds a surrounding JFrame and 
     * runs the application.
     * @param args
     * @throws RemoteException
     * @throws SimulationException 
     */
    public static void main(String[] args) throws RemoteException, SimulationException
    {
        JFrame frame = new JFrame("Traffic Events Animator");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1050,450);
        TrafficEventsAnimator display = new TrafficEventsAnimator();
        frame.add(display);
        frame.setVisible(true);
        display.load();
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollBar scrollBar;
    private javax.swing.JTextArea txtDisplay;
    // End of variables declaration//GEN-END:variables
}
