#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <EEPROM.h>
#include <Adafruit_Sensor.h>
#include "DHT.h"

const char *ssid = "Bill1389";
const char *password = "B4cvxw43bt";

#define GH_INCLUDE_PORTAL
#include <GyverHub.h>
GyverHub hub("MyDevices", "ESP", "");

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

const int ledPin = D4; // Указывайте пин, на котором подключен светодиод
const int fanRelay = D3; // Указывайте пин, на котором подключен светодиод

#define DHTPIN 4           // пин (D2) подключения контакта DATA
#define DHTTYPE DHT22      // датчик DHT 22 
#define INTERVAL_GET_DATA 2000  // интервала измерений, мс
// создание экземпляра объекта DHT
DHT dht(DHTPIN, DHTTYPE);
// переменная для интервала измерений 
unsigned long millis_int1=0;


void writeIntToEEPROM(int address, int value)
{
  // EEPROM.begin(sizeof(value));
  EEPROM.put(address, value);
  EEPROM.commit();
  // EEPROM.end();
}

int readIntFromEEPROM(int address)
{
  int value;
  // EEPROM.begin(sizeof(value));
  EEPROM.get(address, value);
  // EEPROM.end();
  return value;
}

int switchLightState;
int switchLightStateOld;
int currentTimeSec;
int startTime;
int stopTime;
int startTimeOld;
int stopTimeOld;

int setHumidity;
int setTemp;
int setHumidityOld;
int setTempOld;
int currentHumidity;
float currentTemp;

char currentTime[10]; // Выделение памяти под строку

void checkLight()
{
  // Получаем текущее время
  int currentHour = timeClient.getHours() + 3;
  int currentMinute = timeClient.getMinutes();
  int currentSeconds = timeClient.getSeconds();

  if (startTimeOld != startTime)
  {
    writeIntToEEPROM(sizeof(int), startTime);
    Serial.println(startTime);

    startTimeOld = startTime;
  }

  if (stopTimeOld != stopTime)
  {

    writeIntToEEPROM(2 * sizeof(int), stopTime);
    Serial.println(stopTime);
    stopTimeOld = stopTime;
  }

  snprintf(currentTime, sizeof(currentTime), "%02d:%02d", currentHour, currentMinute);
  currentTimeSec = currentHour * 3600 + currentMinute * 60 + currentSeconds;
  // Проверяем условие освещения

  if (switchLightState != switchLightStateOld)
  {
    writeIntToEEPROM(0, switchLightState);
    switchLightStateOld = switchLightState;
  }

  switch (switchLightState)
  {
  case 0:
    digitalWrite(ledPin, LOW); // Включаем светодиод
    break;
  case 1:
    digitalWrite(ledPin, HIGH); // Выключаем светодиод
    break;
  case 2:
    //if (((currentHour >= startHours) and (currentMinute >= startMinutes)) and ((currentHour <= stopHours) and (currentMinute < stopMinutes)))
    if((startTime <= currentTimeSec) and ( currentTimeSec <= stopTime))
    {
      digitalWrite(ledPin, LOW); // Включаем светодиод
    }
    else
    {
      digitalWrite(ledPin, HIGH); // Выключаем светодиод
    }
    break;

  default:
    digitalWrite(ledPin, HIGH); // Выключаем светодиод
    break;
  }
}


int get_data_humidity() {
   int h = dht.readHumidity();
   return h;
}
float get_data_temperature() {
   float h = dht.readTemperature();
   return h;
}
void manageClimate()
{
  currentHumidity = get_data_humidity();
  currentTemp = get_data_temperature();

    if (setTemp != setTempOld)
  {
    writeIntToEEPROM(3 * sizeof(int), setTemp);
    setTempOld = setTemp;
  }


  if (setHumidity != setHumidityOld)
  {
    writeIntToEEPROM(4 * sizeof(int), setHumidity);
    setHumidityOld = setHumidity;
  }

  if(currentTemp < setTemp)
  {
    digitalWrite(fanRelay, LOW); // Включаем светодиод
  } else {
    digitalWrite(fanRelay, HIGH); // Выключаем светодиод
  }



}
// обработчик кнопки (см. ниже)
void btn_cb()
{
  Serial.println("click 4");
}

// обработчик кнопки с информацией о билде (см. ниже)
void btn_cb_b(gh::Build &b)
{
  Serial.print("click 5 from client ID: ");
  Serial.println(b.client.id);
}

void build(gh::Builder &b)
{

  b.Title_(F("title1")).value("Освещение");
  if (b.beginRow())
  {
    b.Time_("startTime", &startTime).label("Время включения").size(2);
    b.Label_(F("currentTime")).label("Текущее время").color(0xd55f30).size(2);

    b.Time_("stopTime", &stopTime).label("Время отключения").size(2);
    b.endRow();
  }

  {
    gh::Row r(b);
    b.Tabs_("tab", &switchLightState).text("Включить;Выключить;По таймеру").label("Выключатель света").size(3);
  }

   
    b.Title_(F("title2")).value("Настройка климата");
  if (b.beginRow())
  {
    b.Spinner_("setTemp", &setTemp).label("Поддерживать температуру").size(3);
    b.Spinner_("setHumidity", &setHumidity).label("Задать максимальную влажость").size(3);
    b.endRow();
  }
    b.Title_(F("title3")).value("Данные датчиков");
  if (b.beginRow())
  {
    b.Label_(F("currentTemp")).label("Температура").color(0xd55f30).size(2);
    b.Label_(F("currentHumidity")).label("Влажность").color(0xd55f30).size(2);
    b.endRow();
  }

}

void setup()
{
  Serial.begin(9600);
  EEPROM.begin(128);
  dht.begin();         // запуск DHT  
  switchLightState = readIntFromEEPROM(0);

  startTime = readIntFromEEPROM(sizeof(int));
  stopTime = readIntFromEEPROM(2 * sizeof(int));
  setTemp = readIntFromEEPROM(3 * sizeof(int));
  setHumidity = readIntFromEEPROM(4 * sizeof(int));


  // Подключение к WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Инициализация светодиода
  pinMode(ledPin, OUTPUT);
  pinMode(fanRelay, OUTPUT);

  // Настройка NTP
  timeClient.begin();

  hub.config(F("MyDevices"), F("ESP"), F(""));
  //hub.mqtt
  // подключить билдер
  hub.onBuild(build);

  // запуск!
  hub.begin();
}

void loop()
{
  timeClient.update(); // Обновляем время
  checkLight();

  hub.tick();

  static gh::Timer tmr(1000); // период 1 секунда
  // каждую секунду будем обновлять заголовок
  if (tmr)
  {
    manageClimate();
    hub.update(F("currentTime")).value(String(currentTime));
    hub.update(F("currentHumidity")).value(String(currentHumidity)+'%');
    hub.update(F("currentTemp")).value(String(currentTemp)+ "C");
    
      
  }
}