#include <Homie.h>

#include "DHTesp.h"
DHTesp dht;
const int TEMPERATURE_INTERVAL = 60;
unsigned long lastTemperatureSent = 0;

const int PIN_RELAY = D1;
#define OUTPUT_SET(x)  digitalWrite(PIN_RELAY, x ? LOW : HIGH)
unsigned int timer = 0;
unsigned int next_timer_update = 0;
HomieNode powerNode("power", "Power", "switch");
HomieNode temperatureNode("temperature", "Temperature", "temperature");

bool powerStateHandler(const HomieRange& range, const String& value) {
    if (value != "on" && value != "off") return false;
    powerNode.setProperty("state").send(value);
    powerNode.setProperty("timer").send("0");
    timer = 0;
    if(value == "on") {
      OUTPUT_SET(true);
      Homie.getLogger() << "Power is on" << endl;
    } else {
      OUTPUT_SET(false);
      Homie.getLogger() << "Power is off" << endl;
    }
    
    return true;
}

bool powerTimerHandler(const HomieRange& range, const String& value) {
    int settimer = value.toInt();
    if(settimer == 0 || settimer > 120) 
         return false;

    timer = millis() + (settimer * 1000 * 60);
    next_timer_update = millis() + 60*1000;
    powerNode.setProperty("timer").send(String(settimer));
    powerNode.setProperty("state").send("on");
    Homie.getLogger() << "Power is on for " << settimer << "minutes" << endl;
    OUTPUT_SET(true);
    return true;
}


void setupHandler() {
  pinMode(PIN_RELAY, OUTPUT);
  OUTPUT_SET(false);
  powerNode.setProperty("state").send("off");
  powerNode.setProperty("timer").send("0");

    
  dht.setup(D1, DHTesp::DHT11); // Connect DHT sensor to GPIO 17
}

void loopHandler() {
  if(timer)
  {
    if(timer < millis()) 
    { //Timer has expired. (Ignore the wraparound...)
      timer = 0;
      OUTPUT_SET(false);
      powerNode.setProperty("timer").send("0");
      powerNode.setProperty("state").send("off");
    }

    if(next_timer_update && millis() > next_timer_update) {
      next_timer_update = millis() + 60*1000;
      unsigned int time_remaining = timer - millis();
      unsigned int min_left = time_remaining / (60*1000);
      powerNode.setProperty("timer").send(String(min_left));

    }
  }

  if (millis() - lastTemperatureSent >= TEMPERATURE_INTERVAL * 1000UL || lastTemperatureSent == 0)
  {
    float humidity = dht.getHumidity();
    float temperature = dht.getTemperature();

    Homie.getLogger() << "Temperature: " << temperature << "°C " << humidity << "% Humidty" << endl;
    temperatureNode.setProperty("temperature").send(String(temperature));
    temperatureNode.setProperty("humidity").send(String(humidity));
    lastTemperatureSent = millis();
  }
}

void setup() {
    Serial.begin(115200);

    Homie_setFirmware("deskcontrol", "0.3.2");
    
    Homie.disableResetTrigger();
    powerNode.advertise("state").settable(powerStateHandler);
    powerNode.advertise("timer").settable(powerTimerHandler);

    temperatureNode.advertise("humidity");
    temperatureNode.advertise("temperature");

    Homie.setSetupFunction(setupHandler);
    Homie.setLoopFunction(loopHandler);

    Homie.setup();
}

void loop() {
    Homie.loop();
}
