package atmsdriver;

import atmsdriver.model.Network;
import java.io.File;
import java.io.FileInputStream;
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"),
        LOOP_FILE_NAME("LoopFileName"),
        NETWORK_FILE_NAME("NetworkFileName"),
        EXCHANGE_FILE_NAME("ExchangeFileName"),
        FEP_WRITER_HOST("FEPWriterHost"),
        FEP_WRITER_PORT("FEPWriterPort");

        public String name;

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

    /** Network model. */
    final private Network network;
    
    /** Sleep Time (10 seconds). **/
    private static final int SLEEP_TIME = 10000;
    
    /** 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(network.toXML());
            network.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);
        }

        network = new Network(
                new File(ATMSDriverProperties.getProperty(
                                PROPERTIES.LDS_FILE_NAME.name)),
                new File(ATMSDriverProperties.getProperty(
                                PROPERTIES.LOOP_FILE_NAME.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);
        }
    }
}
