package atmsdriver;

import atmsdriver.model.Highways;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * ATMS Driver reads the current simulation traffic conditions from the
 * EXCHANGE.XML file and constructs the Highway Network status info in the
 * format required by the FEP. It then sends this XML data over a socket to the
 * FEP Simulator.
 *
 * @author John A. Torres
 * @version 09/10/2017
 */
public class ATMSDriver implements Runnable {

    /**
     * ATMSDriver Error logger.
     */
    private static Logger ATMSDriverLogger = Logger.getLogger("atmsdriver");

    private static final String CONFIG_FILE_NAME = "atms_driver_config.properties";

    /**
     * Properties object for the CADClient class.
     */
    private Properties ATMSDriverProperties;

    /**
     * Enumeration containing properties name values. See ATMSDriver class
     * description for more information.
     *
     * @author John Torres
     * @see ATMSDriver
     */
    private static enum PROPERTIES {
        LDS_FILE_NAME("LDSFileName"),
        LOOPS_FILE_NAME("LoopsFileName"),
        HIGHWAY_META_FILE("HighwayMetaFileName"),
        EXCHANGE_FILE_NAME("ExchangeFileName"),
        FEP_WRITER_HOST("FEPWriterHost"),
        FEP_WRITER_PORT("FEPWriterPort");

        public String name;

        private PROPERTIES(String n) {
            name = n;
        }
    }

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

    /**
     * Sleep Time (30 seconds). *
     */
    private static final int SLEEP_TIME = 30000;

    /**
     * Exchange Reader
     */
    private ExchangeReader exchangeReader;

    @Override
    public void run() {
        // Check for packets and update the simulator
        while (true) {
            // Flush the input file
            ExchangeInfo exInfo = exchangeReader.parse(ATMSDriverProperties
                    .getProperty(PROPERTIES.EXCHANGE_FILE_NAME.name));

            System.out.println(highways.toXML());
            highways.writeToFEP();
            // Update if exchangeInfo is recieved
            if (exInfo != null) {
                // TODO: handle this condition
                Logger.getLogger("ATMSDriver").log(Level.INFO, "exInfo is not null");
            }

            // Wait for FEP Sim to process the data we just sent
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }

    public ATMSDriver(String propertiesFile) {

        if (!verifyProperties(propertiesFile)) {
            System.exit(0);
        }

        highways = new Highways(
                ATMSDriverProperties.getProperty(
                                PROPERTIES.LDS_FILE_NAME.name),
                ATMSDriverProperties.getProperty(
                                PROPERTIES.LOOPS_FILE_NAME.name),
                ATMSDriverProperties.getProperty(
                                PROPERTIES.HIGHWAY_META_FILE.name),
                ATMSDriverProperties.getProperty(PROPERTIES.FEP_WRITER_HOST.name),
                Integer.parseInt(ATMSDriverProperties.getProperty(
                                PROPERTIES.FEP_WRITER_PORT.name)));
        
        exchangeReader = new ExchangeReader();
    }

    private boolean verifyProperties(String propertiesFile) {
        // Load the properties file.
        try {
            ATMSDriverProperties = new Properties();
            ATMSDriverProperties.load(new FileInputStream(propertiesFile));
        } catch (Exception e) {
            ATMSDriverLogger.logp(Level.SEVERE, "ATMSDriver",
                    "Constructor", "Exception in reading properties file.", e);
        }

        return true;
    }

    /**
     * Runs the ATMS Driver.
     */
    public static void main(String[] args) {
        try {
            if (System.getProperty("ATMSDRIVER_PROPERTIES") != null) {
                new Thread(new ATMSDriver(System.getProperty(
                        "ATMSDRIVER_PROPERTIES"))).start();
            } else {
                throw new Exception("ATMSDRIVER_PROPERTIES system property not defined.");
            }
        } catch (Exception e) {
            ATMSDriverLogger.logp(Level.SEVERE, "ATMSDriver", "Main",
                    "Error occured initializing application", e);
            System.exit(-1);
        }
    }
}
