#include <Arduino.h>
#include <MQTT.h>
#include <SPI.h>
#include <Ticker.h>
#include <SpiShiftRegisterChain.h>
#include <Adafruit_NeoPixel.h>
#include <glblData.h>

const int latchPin = 4;
const int dataLengthBytes = 3;
SpiShiftRegisterChain ios(latchPin, dataLengthBytes);
Adafruit_NeoPixel pixels(12, 12, NEO_GRB + NEO_KHZ800);
Ticker valveTiming;
Ticker closeValves;
MQTT connections;
bool init_done = false;


void valveState(void){
  static uint8_t v_powered = MOTOR_POWER_TIME;
  for(uint8_t i=1;i<NUM_VALVES;i++){
    switch(glblData.valveState[i]){
      case VALVE_CLOSED:
        if(glblData.setValveState[i]){
          glblData.valveState[i] = VALVE_OPENING_COILPWR;
          SET_V(i);
        }
        break;
      case VALVE_OPENING_COILPWR:
        glblData.valveState[i] = VALVE_OPENING_POWER;
        KEEP_V(i);
        break;
      case VALVE_OPEN:
        if(!glblData.setValveState[i]){
          glblData.valveState[i] = VALVE_CLOSING_COILPWR;
          RST_V(i);
        }
        break;
      case VALVE_CLOSING_COILPWR:
        glblData.valveState[i] = VALVE_CLOSING_POWER;
        KEEP_V(i);
        break;
      case VALVE_OPENING_POWER:
        glblData.valveState[i] = VALVE_OPENING_POWER_COILPWR;
        SET_V(0);
        break;
      case VALVE_OPENING_POWER_COILPWR:
        glblData.valveState[i] = VALVE_OPEN_MOTORIZED;
        v_powered = 0;
        KEEP_V(0);
        break;
      case VALVE_CLOSING_POWER:
        glblData.valveState[i] = VALVE_CLOSING_POWER_COILPWR;
        SET_V(0);
        break;
      case VALVE_CLOSING_POWER_COILPWR:
        glblData.valveState[i] = VALVE_CLOSED_MOTORIZED;
        v_powered = 0;
        KEEP_V(0);
        break;
      case VALVE_OPEN_MOTORIZED:
        if(v_powered >= MOTOR_POWER_TIME){
          glblData.valveState[i] = VALVE_OPEN_COILPWR;
          RST_V(0);
        }
        break;
      case VALVE_OPEN_COILPWR:
        glblData.valveState[i] = VALVE_OPEN;
        KEEP_V(0);
        break;
      case VALVE_CLOSED_MOTORIZED:
        if(v_powered >= MOTOR_POWER_TIME){
          glblData.valveState[i] = VALVE_CLOSED_COILPWR;
          RST_V(0);
        }
        break;
      case VALVE_CLOSED_COILPWR:
        glblData.valveState[i] = VALVE_CLOSED;
        KEEP_V(0);
        break;
    }
  }
  if(v_powered < MOTOR_POWER_TIME){
    v_powered++;
  }
}

void closeValves_tick(uint8_t state){
  switch(state){
    case 0:
      ios.setDataToZeros();
      ios.writeData();
      for(uint8_t i=0;i<8;i++){
        ios.setBitOn(i);
      }
      ios.writeData();
      closeValves.once(0.5,closeValves_tick,(uint8_t)1);  //plan next step
      break;
    case 1:
      for(uint8_t i=0;i<8;i++){
        ios.setBitOff(i);
      }
      ios.writeData();
      SET_V(0);
      closeValves.once(0.5,closeValves_tick,(uint8_t)2);  //plan next step
      break;
    case 2:
      KEEP_V(0);
      closeValves.once(20,closeValves_tick,(uint8_t)3);  //plan next step
      break;
    case 3:
      RST_V(0);
      closeValves.once(0.5,closeValves_tick,(uint8_t)4);
      break;
    case 4:
      KEEP_V(0);
      init_done = true;
      valveTiming.attach_ms(500,valveState);
      break; 
  }
}

void init_relays(){
  closeValves.once(0.2,closeValves_tick,(uint8_t)0);
}

void setup() {
  pixels.clear();
  pixels.show();
  Serial.begin(115200);
  Serial.println("Hello");
  connections.begin();
 // statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
 // millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");

 // ESPUI.begin(connections.getHostname());
  
  SPI.begin();
  //pixels.setPixelColor(0,pixels.Color(200,100,0));
  //pixels.show();
  
  
  
  //init_relays();
}

static long oldTime = 0;
unsigned long lastTick = millis();
void loop() {
  connections.loop();
  if(init_done){
    //pixels.setPixelColor(0,pixels.Color(0,100,0));
    //pixels.show();
  }
  if (millis() - oldTime > 5000){
        //ESPUI.print(millisLabelId, String(millis()));
        oldTime = millis();
    }
  // put your main code here, to run repeatedly:
}

