SYSTEM_MODE(SEMI_AUTOMATIC);

//State : 0=Heat OFF ; 1=Heat ON;
// 2=Heat Turning OFF; 3 = Heat Water
int State = 0;

int button = 0;
int button_prev = 0;

bool ONCondPrev = 0;
bool ONCond = 0;

int lastSync = 0;
int Timing = 0;
int Heating = 0;
int OFFTimer = 0;
int ONHour = 06;
int ONMinute = 00;
int tempDOWNInt = 0;
int tempOUTInt = 0;
int tempWATERInt = 0;
int setpointInt = 0;

float setpoint = 0;
float setpointDOWN = 20.5;
float setWater = 40;
float tempDOWN = 0;
float tempOUT = 0;
float tempWATER = 0;
float tempPot = 0;
float  EPS = 0.3;

char resultstr[64];

void setup() {
    Spark.function("SetVal",set_val);
    Spark.variable("tempDOWN", &tempDOWNInt, INT);
    Spark.variable("tempOUT", &tempOUTInt, INT);
    Spark.variable("tempWATER", &tempWATERInt, INT);
    Spark.variable("State", &State, INT);
    Spark.variable("Setpoint", &setpointInt, INT);
    Spark.variable("Timing", &Timing, INT);
    Spark.variable("Heating", &Heating, INT);
    Spark.variable("result", &resultstr, STRING); 
    
    lastSync = Time.now();
    
    pinMode(D0, OUTPUT); // Heat Control
    pinMode(D1, OUTPUT); // Upstairs Rads Control
    pinMode(D2, OUTPUT); // Downstairs Rads Control
    pinMode(D3, OUTPUT); // Heat LED
    pinMode(D4, OUTPUT); // Upstairs Rads LED
    pinMode(D5, OUTPUT); // Downstairs Rads LED
    
    pinMode(A0, INPUT); // TEMP Sensor 0
    pinMode(A1, INPUT); // TEMP Sensor 1
    pinMode(A2, INPUT); // TEMP Sensor 2
    
    pinMode(D6, INPUT); // Push Button
    pinMode(A4, INPUT); // Potentiometer
    
    pinMode(A5, OUTPUT); // LED BLUE
    pinMode(A6, OUTPUT); // LED GREEN
    pinMode(A7, OUTPUT); // LED RED
    
    State = 0;
    ONCond = 1;
    Time.zone(1);  // GMT +/-
    
    // Connect to Cloud Unless Button is Pressed on Startup
    if(!digitalRead(D6)) Spark.connect();
}

void loop() {
    sprintf(resultstr, "{\"data1\":%d,\"data2\":%d,\"data3\":%d,\"data4\":%d}", tempDOWNInt, tempWATERInt, tempOUTInt, State); 
    
    // Sync Time?
    if(Time.now() > lastSync+86400) {
        Spark.syncTime();
        lastSync = Time.now();
    }
    
    // Update Button State
    delay(100);
    button_prev = button;
    button = digitalRead(D6);
    
    // Read Temperatures
    // LM35
    tempDOWN = 0.02*(analogRead(A0)*330.0/4095-2) + 0.98*tempDOWN;
    tempDOWNInt = int(tempDOWN*10);  // Report to 1 decimal place
    // TMP36
    tempWATER = 0.02*(analogRead(A1)*3.3/4095-0.5)*100 + 0.98*tempWATER;
    tempWATERInt = int(tempWATER*10);  // Report to 1 decimal place
    // TMP36
    tempOUT = 0.02*(analogRead(A2)*3.3/4095-0.5)*100 + 0.98*tempOUT;
    tempOUTInt = int(tempOUT*10);  // Report to 1 decimal place
    
    // Read Potentiometer
    tempPot = 0.1*map(analogRead(A4),0,4096,15,25 )+ 0.9*tempPot;
    if (tempPot > setpointDOWN) setpoint = tempPot;
    else setpoint = setpointDOWN;
    setpointInt = int(setpoint*10);  // Report to 1 decimal place
    
    // OFF Timer
    if (Timing && Time.now()>OFFTimer) {
        Timing = 0;
        State = 0;
    }
    
    // ON Timer
    ONCondPrev = ONCond;
    ONCond = Time.hour() >= ONHour && Time.minute() >= ONMinute;
    if (!ONCondPrev && ONCond) {
        State = 3;
    }
    
    switch(State) {
        case 0: { // Heat OFF
            digitalWrite(D0,LOW); // Heat OFF
            digitalWrite(D3,LOW); // Heat LED OFF
            digitalWrite(D1,LOW); // Upstairs Rads OFF
            digitalWrite(D4,LOW); // Upstairs Rads LED OFF
            digitalWrite(D2,LOW); // Downstairs Rads OFF
            digitalWrite(D5,LOW); // Downstairs Rads LED OFF
            Heating = 0;
            // BLUE LED
            analogWrite(A5,255);
            analogWrite(A6,0);
            analogWrite(A7,0);
            
            // Button press?
            if (!button_prev && button) {
                delay(20);
                if (digitalRead(D6)) State = 1;  // Short Press
                delay(1000);
                if (digitalRead(D6)) State = 3; // Long Press
            }
            break;
        }
        case 1: { // Heat ON
            digitalWrite(D0,HIGH);// Heat ON
            digitalWrite(D3,HIGH); // Heat LED ON
            if (tempDOWN <= setpoint)  {// s/b tempUP!!! <<<<<<<<<
                digitalWrite(D1,HIGH); // Upstairs Rads ON
                digitalWrite(D4,HIGH); // Upstairs Rads LED ON
                // RED LED
                analogWrite(A5,0);
                analogWrite(A6,0);
                analogWrite(A7,255);
                Heating = 1;
            }
            if (tempDOWN >= setpoint+EPS)  {// s/b tempUP!!! <<<<<<<<<
                digitalWrite(D1,LOW); // Upstairs Rads OFF
                digitalWrite(D4,LOW); // Upstairs Rads LED OFF
                // MAGENTA LED
                analogWrite(A5,255);
                analogWrite(A6,0);
                analogWrite(A7,255);
                Heating = 0;
            }
            if (tempDOWN <= setpoint)  {
                digitalWrite(D2,HIGH); // Downstairs Rads ON
                digitalWrite(D5,HIGH); // Downstairs Rads LED ON
                // RED LED
                analogWrite(A5,0);
                analogWrite(A6,0);
                analogWrite(A7,255);
                Heating = 1;
            }
            if (tempDOWN >= setpoint+EPS)  {
                digitalWrite(D2,LOW); // Downstairs Rads OFF
                digitalWrite(D5,LOW); // Downstairs Rads LED OFF
                // MAGENTA LED
                analogWrite(A5,255);
                analogWrite(A6,0);
                analogWrite(A7,255);
                Heating = 0;
            }
            // Button press?
            if (!button_prev && button) {
                delay(20);
                if (digitalRead(D6)) State = 2;  // Short Press
                delay(1000);
                if (digitalRead(D6)) State = 3; // Long Press
            }
            break;
        }
            case 2: { // Heat Turning OFF
            digitalWrite(D0,LOW); // Heat OFF
            digitalWrite(D3,LOW); // Heat LED OFF
            digitalWrite(D1,HIGH); // Upstairs Rads ON
            digitalWrite(D4,HIGH); // Upstairs Rads LED ON
            digitalWrite(D2,HIGH); // Downstairs Rads ON
            digitalWrite(D5,HIGH); // Downstairs Rads LED ON
            Heating = 0;
            // BLUE LED
            analogWrite(A5,255);
            analogWrite(A6,0);
            analogWrite(A7,0);
            
            if (Timing == 0) {
                OFFTimer = Time.now()+1800; // Timer expires 30min from now
                Timing = 1;
            }
            
            // Button press?
            if (!button_prev && button) {
                delay(20);
                if (digitalRead(D6)) {
                    State = 1;  // Short Press
                    Timing = 0;
                }
                delay(1000);
                if (digitalRead(D6)) {
                    State = 0; // Long Press
                    Timing = 0;
                }
            }
            break;
        }
            case 3: { // Heat Water
            if (tempWATER <= setWater) {
                digitalWrite(D0,HIGH); // Heat ON
                digitalWrite(D3,HIGH); // Heat LED ON
                digitalWrite(D1,LOW); // Upstairs Rads OFF
                digitalWrite(D4,LOW); // Upstairs Rads LED OFF
                digitalWrite(D2,LOW); // Downstairs Rads OFF
                digitalWrite(D5,LOW); // Downstairs Rads LED OFF
                // GREEN LED
                analogWrite(A5,0);
                analogWrite(A6,255);
                analogWrite(A7,0);
                // Set Timer
                if (!Timing) {
                OFFTimer = Time.now()+7200; // Timer expires 120min from now
                Timing = 1;
                }
            }
            else {
                // Cancel Timer
                Timing = 0;
                // Turn off
                State = 0;
            }
            Heating = 0;
            
            // Button press?
            if (!button_prev && button) {
                delay(20);
                if (digitalRead(D6)) {
                    State = 1;  // Short Press
                    Timing = 0;
                }
                delay(1000);
                if (digitalRead(D6)) {
                    State = 0; // Long Press
                    Timing = 0;
                }
            }
            break;
        }
    }
}

int set_val(String command)
{
    int entryState = State;
    
    if(command.substring(0,6) == "STATE:") {  // "STATE:0"
        State = (command.charAt(6) - '0');
        return 1;
    }
    else if (command.substring(0,8) == "SETDOWN:") {  // "SETDOWN:18.5"
        setpointDOWN = 10*(command.charAt(8) - '0')+(command.charAt(9) - '0')+0.1*(command.charAt(11) - '0');
        return 1;
    }
    else return -1;
    // Cancel Timers if necessary
    if(Timing && entryState!=State) Timing=0;
}