/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sensors;

import CommonFunctions.debugPrinter;
import applications.CarbonControl;
import mdot.Main;
import structures.Constants;

/*class Sensor
 * Contains functions dealing with OBD sensors
 *
 */
public class Sensor {

    private String name;        //name of sensor
    private String pid;         //command to send ot OBD
    private int bytes;          //number of bytes expected from OBD
    private double prevValue;
    private String hashName;

    //constructor
    public Sensor(String Name, String PID, String hashName, int Bytes, double prevValue)
    {

        this.name = Name;
        this.pid = PID;
        this.hashName = hashName;
        this.bytes = Bytes;
        this.prevValue = prevValue;

    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the pid
     */
    public String getPid() {
        return pid;
    }

    /**
     * @return the bytes
     */
    public int getBytes() {
        return bytes;
    }

      /**
     * @return the prevValue
     */
    public double getPrevValue() {
        return prevValue;
    }

    /**
     * @param prevValue the prevValue to set
     */
    public void setPrevValue(double prevValue) {
        this.prevValue = prevValue;
    }

    //Takes as input a response from the sensor and calls the corresponding
    //sensor function.
    public double calculate(Sensor s, byte[] data)
    {
        double result = -1;

        String stringresponse  = new String(data);
        String[] dataBytes =  stringresponse.split(" ");

        if(dataBytes.length < 3){
            //debugPrinter.printLine(s.getName() + ": DATA NOT AVAILABLE");


            if(s.getHashName().equals(Constants.HASH_RPM))
            {
                Main.getMe().replaceObjectAsString(s.getHashName(), "N/A");
                Main.getMe().replaceObjectAsString(Constants.HASH_ENGINE_STATE, "OFF");
            }
            else
                Main.getMe().replaceObjectAsString(s.getHashName(), "N/A");



            return result;
        }

        if(s.getName().equals(Constants.SENSOR_ENGINE_RPM))
            result = engine_rpm(dataBytes[2], dataBytes[3]);
        else if(s.getName().equals(Constants.SENSOR_VEHICLE_SPEED))
            result = vehicle_speed(dataBytes[2]);
        else if(s.getName().equals(Constants.SENSOR_MAF))
            result = MAF(dataBytes[2], dataBytes[3]);
         else if(s.getName().equals(Constants.SENSOR_FUEL_LEVEL))
            result = fuel_level(dataBytes[2]);
         else if(s.getName().equals(Constants.SENSOR_FUEL_PRESSURE))
            result = fuel_pressure(dataBytes[2]);
         else if(s.getName().equals(Constants.SENSOR_INTAKE_AIR_TEMP))
            result = intake_air_temp(dataBytes[2]);
         else if(s.getName().equals(Constants.SENSOR_THROTTLE_POSN))
            result = throttle_posn(dataBytes[2]);
         else if(s.getName().equals(Constants.SENSOR_ENGINE_LOAD))
            result = engine_load(dataBytes[2]);
         else if(s.getName().equals(Constants.SENSOR_ENGINE_COOLANT_TMP))
            result = engine_coolant_temp(dataBytes[2]);


            return result;
    }

    private double engine_rpm(String a, String b)
    {
        double result = -1;
        int A;
        int B;

        try{
        A = Integer.parseInt(a,16);
        B = Integer.parseInt(b, 16);
        //RPM formula -- ((A*256)+B)/4

        result = ((A*256) + B)/4;
        }
        catch(Exception e){

            result = -1;
        }

        return result;
    }

    private double vehicle_speed(String a)
    {
        double result = -1;
        double constant = 0.621371192;

        int A;

        try{
        A = Integer.parseInt(a,16);

        result = (A * constant); //change to miles/hour
        }
         catch(Exception e){

            result = -1;
        }

        return result;
    }

    private double fuel_level(String a)
    {
        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (100*A)/255; //100*A/255
        }
         catch(Exception e){

            result = -1;
        }

        return result;
    }


    private double MAF(String a, String b)
    {
        double result = -1;

        //((256*A)+B) / 100

        int A,B;
        try{
        A = Integer.parseInt(a,16);
        B = Integer.parseInt(b,16);

        result = ((256*A)+B)/100; // grams of air/second
        }
         catch(Exception e){

            result = -1;
        }


        return result;
    }

    private double fuel_pressure(String a)
    {

        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (A*3);
        }
         catch(Exception e){

            result = -1;
        }

        return result;

    }
    
    private double intake_air_temp(String a)
    {
        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (A-40);
        }
         catch(Exception e){

            result = -1;
        }

        return result;
       
    }


    private double throttle_posn(String a)
    {
        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (A*100)/255;
        }
         catch(Exception e){

            result = -1;
        }

        return result;

    }

    private double engine_load(String a)
    {
        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (A*100)/255;
        }
         catch(Exception e){

            result = -1;
        }

        return result;

    }

    private double engine_coolant_temp(String a)
    {
        double result = -1;


        int A;
        try{
        A = Integer.parseInt(a,16);

        result = (A-40);
        }
         catch(Exception e){

            result = -1;
        }

        return result;

    }

    //Prints sensor data to the screen and puts it in the context
    public void printSensorData(Sensor s, double result){

        String sname = s.getName();

        if(result == -1)
            return;


        if(sname.equals(Constants.SENSOR_VEHICLE_SPEED))
        {
            //debugPrinter.printLine(sname + ": " + result);
            Main.getMe().setObjectAsDouble(Constants.HASH_SPEED, result);
        }
        else if(sname.equals(Constants.SENSOR_MAF))
        {
            //debugPrinter.printLine(sname + ": " + result + " g/s");
            Main.getMe().setObjectAsDouble(Constants.HASH_MAF, result);
        }
        else if(sname.equals(Constants.SENSOR_FUEL_PRESSURE))
        {
            //debugPrinter.printLine(sname + ": " + result + " kPa");
            Main.getMe().setObjectAsDouble(Constants.HASH_FUEL_PRESSURE, result);
        }
        else if(sname.equals(Constants.SENSOR_INTAKE_AIR_TEMP))
        {
            //debugPrinter.printLine(sname + ": " + result + " ° C");
            Main.getMe().setObjectAsDouble(Constants.HASH_INTAKE_AIR_TMP, result);
        }
        else if(sname.equals(Constants.SENSOR_THROTTLE_POSN))
        {
            //debugPrinter.printLine(sname + ": " + result + " %");
            Main.getMe().setObjectAsDouble(Constants.HASH_THROTTLE_POSN, result);
        }
        else if(sname.equals(Constants.SENSOR_ENGINE_LOAD))
        {
            //debugPrinter.printLine(sname + ": " + result + " %");
            Main.getMe().setObjectAsDouble(Constants.HASH_ENGINE_LOAD, result);
        }
        else if(sname.equals(Constants.SENSOR_ENGINE_COOLANT_TMP))
        {
            //debugPrinter.printLine(sname + ": " + result + " ° C");
            Main.getMe().setObjectAsDouble(Constants.HASH_ENGINE_COOLANT_TMP, result);
        }
        else if(sname.equals(Constants.SENSOR_FUEL_LEVEL)){
            //debugPrinter.printLine(sname + ": " + result + "%");
            Main.getMe().setObjectAsDouble(Constants.SENSOR_FUEL_LEVEL, result);
        }
        else if(sname.equals(Constants.SENSOR_ENGINE_RPM))
        {
            if(result == 0){
                //debugPrinter.printLine("ENGINE OFF");
                Main.getMe().setObjectAsString(Constants.HASH_ENGINE_STATE, "OFF");
            }
            else
                Main.getMe().setObjectAsString(Constants.HASH_ENGINE_STATE, "ON");

            //debugPrinter.printLine(sname + ": " + result + " rpm");
             Main.getMe().setObjectAsDouble(Constants.HASH_RPM, result);
            
        }
        return;

    }

    public static void initializeSensors()
    {

        SensorVector sensors = new SensorVector();
        sensors.addSensor(Constants.SENSOR_ENGINE_RPM, "010C\r", Constants.HASH_RPM, 2, 0);
        sensors.addSensor(Constants.SENSOR_VEHICLE_SPEED, "010D\r", Constants.HASH_SPEED, 1, 0);
        sensors.addSensor(Constants.SENSOR_MAF, "0110\r", Constants.HASH_MAF, 2, 0);
        sensors.addSensor(Constants.SENSOR_FUEL_LEVEL, "012F\r", Constants.HASH_FUEL_INPUT_LEVEL, 1, 0);
        sensors.addSensor(Constants.SENSOR_FUEL_PRESSURE, "010A\r", Constants.HASH_FUEL_PRESSURE, 1, 0);
        sensors.addSensor(Constants.SENSOR_INTAKE_AIR_TEMP, "010F\r", Constants.HASH_INTAKE_AIR_TMP, 1, 0);
        sensors.addSensor(Constants.SENSOR_THROTTLE_POSN, "0111\r", Constants.HASH_THROTTLE_POSN, 1, 0);
        sensors.addSensor(Constants.SENSOR_ENGINE_LOAD, "0104\r", Constants.HASH_ENGINE_LOAD, 1, 0);
        sensors.addSensor(Constants.SENSOR_ENGINE_COOLANT_TMP, "0105\r", Constants.HASH_ENGINE_COOLANT_TMP, 1, 0);

    }

    /**
     * @return the hashName
     */
    public String getHashName() {
        return hashName;
    }

    /**
     * @param hashName the hashName to set
     */
    public void setHashName(String hashName) {
        this.hashName = hashName;
    }
}
