/*
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
*/

#include <HomeChef.h>
#include <SandS.h>

HomeChef_Class HomeChef;

HomeChef_Class::HomeChef_Class() { }

void HomeChef_Class::begin() {
	while(!SerialPort.begin(19200, SERIAL_8N1, SERIAL_RS485_FD));
}

// Waits for and reads status packet
// Very little error checking done, no time out
boolean HomeChef_Class::readStatus() {
  byte state = 0;
  char in;
  char pkt[128]; // 128 bytes max
  byte pktix = 0;
  char *str[16] = {&pkt[0]};
  byte strix = 0;
  while(1) {
    while(!SerialPort.available());
    in = SerialPort.read();
    switch(state) {
      case 0:
        if(in == (char)0xFD) state = 1;
        break;
      case 1:
        if(in == (char)0x0A) state = 2;
        else return false;
        break;
      case 2:
        //Serial.write(in); // Debug out: packet content
        if(in == (char)0x0A || in == (char)0x7C) {; // end of data
          pkt[pktix++] = 0x00;
          str[++strix] = &pkt[pktix];
          if(in == 0x0A) state = 3;
        } else {
          pkt[pktix++] = in;
        }
        break;
      case 3:
        if(in == (char)0xFE) {
          // == FIXES A COMM BUG IN THE OVEN ==
          if(strix == 11) {
            for(byte n = 3; n < 10; n++) str[n] = str[n + 1];
            strix = 10;
          }
          // == END FIX =======================
          if(strix != 10) return false; // All packets should have 10 SUBSTR

          //// Debug out: received SUBSTRs
          //Serial.println("");
          //Serial.println(strix);
          //for(byte n = 0; n < strix; n++)
          //Serial.println(str[n]);
          
          ovenLightStatus = strtoul(str[0], NULL, 10);
          applicanceState = strtoul(str[1], NULL, 10);
          strcpy(recipeName, str[2]);
          ovenTemperature = strtoul(str[3], NULL, 10);
          minutesElapsed = strtoul(str[4], NULL, 10);
          minutesRemaining = strtoul(str[5], NULL, 10);
          temperatureSetpoint = strtoul(str[6], NULL, 10);
          activeHeaterSystem = strtoul(str[7], NULL, 10);
          meatProbeTemperature = strtoul(str[8], NULL, 10);
          childLockStatus = strtoul(str[9], NULL, 10);
          return true;
        }
        return false;
    }
  }
}

void HomeChef_Class::setOvenLight(byte request) {
  char pkt[] = "\xFD\x0A""L \x0A\xFE";
  pkt[3] = request ? '1' : '0';
  SerialPort.print(pkt);
}

void HomeChef_Class::setChildLock(byte request) {
  char pkt[] = "\xFD\x0A""B \x0A\xFE";
  pkt[3] = request ? '1' : '0';
  SerialPort.print(pkt);
}

void HomeChef_Class::startCooking() {
  char pkt[] = "\xFD\x0A""C1\x0A\xFE";
  SerialPort.print(pkt);
}

void HomeChef_Class::stopCooking() {
  char pkt[] = "\xFD\x0A""C0\x0A\xFE";
  SerialPort.print(pkt);
}

void HomeChef_Class::uploadRecipe(byte mode, word temperature, word duration) {
  char pkt[] = "\xFD\x0A""U 000000\x0A\xFE";
  pkt[3] = mode | 0x80;
  pkt[6] = (temperature % 10) + '0'; temperature /= 10;
  pkt[5] = (temperature % 10) + '0'; temperature /= 10;
  pkt[4] = (temperature % 10) + '0';
  pkt[9] = (duration % 10) + '0'; duration /= 10;
  pkt[8] = (duration % 10) + '0'; duration /= 10;
  pkt[7] = (duration % 10) + '0';
  SerialPort.print(pkt);
}