package atmsdriver;

import tmcsim.client.*;
import atmsdriver.model.Highways;
import atmsdriver.model.TrafficEvent;
import atmsdriver.model.LoopDetector.DOTCOLOR;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
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.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import tmcsim.common.SimulationException;
import tmcsim.interfaces.CADClientInterface;
import tmcsim.interfaces.CoordinatorInterface;

/**
 * Skeleton for ATMS Driver that reads a "batch" file of highway status update
 * commands.  A console display of the highway network is output
 * for each event.
 * @author jdalbey
 */
public class TrafficModelEventDriver extends UnicastRemoteObject implements
        CADClientInterface
{
    private final static SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    /**
     * Error logger.
     */
    private static Logger cadClientLogger = Logger.getLogger("tmcsim.client");

    @Override
    public void refresh() throws RemoteException
    {
        System.out.println("ATMSBatchDriver.refresh() was invoked.");
    }

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

    /**
     * LinkedList of batch events
     */
    private LinkedList<TrafficEvent> eventQueue;
    /**
     * Map of incidents to events
     */
    private Map<String, List<TrafficEvent>> incidents;

    /**
     * Constructor. Initialize data from parsed properties file. Create a socket
     * connection to the CADSimulator.
     *
     * @param propertiesFile File path (absolute or relative) to the properties
     * file containing configuration data.
     */
    public TrafficModelEventDriver() throws RemoteException
    {
        // Initialize the highway model
        incidents = new HashMap<String, List<TrafficEvent>>();
        highways = new Highways(
                "config/vds_data/highways_fullmap.txt",
                //        "192.168.251.46", 8080);  //IP address of FEP Sim Linux VM
                "localhost", 8080);

        // READ THE BATCH FILE OF COMMANDS and put in a queue
        readBatchFile();

        // If we have any events left to process
        while (!eventQueue.isEmpty())
        {
            // Get the time to launch the next event
            TrafficEvent nextEvent = eventQueue.peek();
            System.out.println("LAUNCHING EVENT: " + nextEvent.toString());
            // apply colorization to highways
            highways.applyColorToHighwayStretch(nextEvent.routeNumber, nextEvent.dir,
                    nextEvent.postmile, nextEvent.range, nextEvent.color);
            System.out.println(highways.toString());
            // Remove this event from the queue, we're done with it.
            eventQueue.remove();

        }

    }

    private void readBatchFile()
    {
        FileInputStream fis;
        try
        {
            fis = new FileInputStream("config/vds_data/atmsBatchEvents.txt");
            eventQueue = new LinkedList<TrafficEvent>();
            // Read all lines from the file of events
            Scanner scan = new Scanner(fis);
            while (scan.hasNext())
            {
                // Read a line and add it to the event queue
                String line = scan.nextLine().trim();
                if (line.charAt(0) != '#')
                {
                    TrafficEvent evt;
                    try
                    {
                        evt = new TrafficEvent(line);
                        eventQueue.add(evt);
                        String incident = evt.incident;
                        // Add the line to the list for the corresponding incident
                        List evtList;
                        if (incidents.containsKey(evt.incident))
                        {
                            evtList = incidents.get(evt.incident);
                        }
                        else
                        {
                            evtList = new ArrayList<String>();
                        }
                        evtList.add(evt);
                        // and put it back in the map
                        incidents.put(incident, evtList);
                    }
                    catch (ParseException ex)
                    {
                        Logger.getLogger(TrafficModelEventDriver.class.getName()).log(Level.SEVERE, null, ex);
                        System.out.println("Wrong format data in batch event file: " + line + " \nskipping.");
                        System.out.println("Skipping badly formatted event.");
                    }
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            Logger.getLogger(TrafficModelEventDriver.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Events file read, " + eventQueue.size() + " events queued.");
        // Put the events in chronological order
        Collections.sort(eventQueue);
    }

    /**
     * Format a time in seconds as HH:MM:SS
     *
     * @param l
     * @return
     */
    private String formatInterval(final long l)
    {
        final long hr = TimeUnit.SECONDS.toHours(l);
        final long min = TimeUnit.SECONDS.toMinutes(l - TimeUnit.HOURS.toSeconds(hr));
        final long sec = TimeUnit.SECONDS.toSeconds(l - TimeUnit.HOURS.toSeconds(hr) - TimeUnit.MINUTES.toSeconds(min));
        return String.format("%02d:%02d:%02d", hr, min, sec);
    }
    /**
     * Construct the CADClient with the properties file path, either from the
     * command line arguments or default.
     *
     * @param args Command line arguments.
     */
    public static void main(String[] args)
    {
        if (System.getProperty("CONFIG_DIR") == null)
        {
            System.setProperty("CONFIG_DIR", "config");
        }

        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            new TrafficModelEventDriver();

        }
        catch (Exception e)
        {
            cadClientLogger.logp(Level.SEVERE, "SimulationManager", "Main",
                    "Error initializing application.");

            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);

            System.exit(-1);
        }

    }

}
