package atmsdriver.model;

import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/** 
 *  A LoopDetector represents a single detector for a single lane in a network.
 * 
 *  A LoopDetector contains static meta data, and three dynamic attributes: vol,
 *  occ, and spd.
 *
 * @author John A. Torres
 * @version 09/10/2017
 */
public class LoopDetector 
{
    /* static data */
    final public int loopID;
    final public String loopLocation;
    final public String loopLocationID;
    
    /* dynamic data */
    public int vol;
    public float occ;
    
    /**
     * Constructs a LoopDetector from loopID, loopLocation, and laneNum
     * 
     * @param loopID
     * @param loopLocation
     * @param laneNum 
     */
    public LoopDetector(int loopID, String loopLocationID, String loopLocation)
    {
        /* Set static data */
        this.loopID = loopID;
        this.loopLocation = loopLocation;
        this.loopLocationID = loopLocationID;
        /* Init dynamic data */
        this.vol = 0;
        this.occ = 0;
    }
    
    /**
     * XML tags used for toXML() method.
     */
    private static enum XML_TAGS
    {
        LOOP_ID("Loop_ID"),
        LOOP_LOCATION("Loop_Location"),
        VOL("Vol"),
        OCC("Occ"),
        LOOP("Loop");
        
        String tag;
        
        private XML_TAGS(String n)
        {
            tag = n;
        }
    }
    
    /** Returns a string of highways data. If MetaDataOnly is true, you get a full
     *  dump of the highways meta data, which does not include dynamic loop values,
     *  and does include the string location names. If MetaDataOnly is false,
     *  dynamic loop values are included, and unnecessary information like string
     *  location values are included.
     * 
     *  The FEPSimulator takes in the toCondensedFormat() output, with a MetaDataOnly
     *  value of false, over the socket.
     * 
     *  The MetaDataOnly flag should be used to get a full dump of the highways
     *  information. This was used to get the highways_fullmap.txt output.
     * 
     * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim
     * @return String, highways data in condensed format
     */
    public String toCondensedFormat(boolean MetaDataOnly)
    {
        StringBuilder build = new StringBuilder();
        build.append(Integer.toString(this.loopID));
        build.append(" ");
        if(!MetaDataOnly)
        {
            build.append(" ");
            build.append(this.occ);
            build.append(" ");
            build.append(this.vol);
            build.append(" ");
        }
        else
        {
            build.append(this.loopLocationID);
        }
        build.append(this.loopLocation);
        build.append("\n");
        return build.toString();
    }
    
    /** 
     * Updates loop detector dynamic attributes.
     * @param vol volume
     * @param occ occupancy
     * @param spd speed
     */
    public void updateLoop(int vol, float occ)
    {
        this.vol = vol;
        this.occ = occ;
    }

    /**
     * Returns the LoopDetector data in XMLFormat
     * 
     * @param currElem The current XML <LoopDetector> element
     */
    public void toXML(Element currElem)
    {
        Document theDoc = currElem.getOwnerDocument();
        
        Element loopElement = theDoc.createElement(XML_TAGS.LOOP.tag);
        currElem.appendChild(loopElement);
        
        Element loopIDElement = theDoc.createElement(XML_TAGS.LOOP_ID.tag);
        loopIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.loopID)));
        loopElement.appendChild(loopIDElement);
        
        Element loopLocElement = theDoc.createElement(XML_TAGS.LOOP_LOCATION.tag);
        loopLocElement.appendChild(theDoc.createTextNode(this.loopLocation));
        loopElement.appendChild(loopLocElement);
        
        Element volElement = theDoc.createElement(XML_TAGS.VOL.tag);
        volElement.appendChild(theDoc.createTextNode(String.valueOf(this.vol)));
        loopElement.appendChild(volElement);
        
        Element occElement = theDoc.createElement(XML_TAGS.OCC.tag);
        occElement.appendChild(theDoc.createTextNode(String.valueOf(this.occ)));
        loopElement.appendChild(occElement);
    }
    
    /**
     * Enum for highway status dot colors. Each color has associated volume
     * and occupancy constants.
     *
     * @author John A. Torres, jdalbey
     * @version 10/11/2017
     */
    public static enum DOTCOLOR {

        RED(1, 0.06f),    // "Stopped" is less than 25mph
        YELLOW(3,0.059f), // speed = 26
        GREEN(0,0);
        
        // All the first letters of the values, in order.
        public static String allLetters = "RYG";
        
        private int vol;  /* volume */
        private float occ;  /* occupancy */      
        
        private DOTCOLOR(int v, float o)
        {
            vol = v;
            occ = o;
        }
        /**
         * Return the first letter of this enum.
         *
         * @return String first letter of this enum.
         */
        public String getLetter() {
            return this.toString().substring(0, 1);
        }

        public int volume()
        {
            return vol;
        }
        public float occupancy()
        {
            return occ;
        }
        /**
         * Returns a dot color given its first character.
         *
         * @param letter the first character of a dot color
         * @return dot color corresponding to letter
         * @pre letter must be one of allLetters
         */
        public static DOTCOLOR toDotColor(String letter) {
            return values()[allLetters.indexOf(letter.charAt(0))];
        }
    }  
    
}
