#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include "RTClib.h"

#define TEMP_PIN 39
#define LED_1_PIN 16

#define MESSURMENT_SWITCH_PIN 2

#define ENCODER_CLK_PIN 25
#define ENCODER_DT_PIN  26

const char* ssid = "Wokwi-GUEST";
const char* password = "";

String deviceId = "12345";

unsigned long lastTime = 0;
unsigned long timerDelay = 10000 ; // 10s

long targetTemperatureInC = 25.0;

LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 20, 4);
RTC_DS1307 RTC;

void setup() {
  initLCD();
  initRTC();

  WiFi.begin(ssid, password, 6);

  pinMode(TEMP_PIN, INPUT);
  pinMode(MESSURMENT_SWITCH_PIN, INPUT);
  pinMode(LED_1_PIN, OUTPUT);

  pinMode(ENCODER_CLK_PIN, INPUT);
  pinMode(ENCODER_DT_PIN, INPUT);

  attachInterrupt(digitalPinToInterrupt(ENCODER_CLK_PIN), readEncoder, FALLING);

  Serial.begin(115200);
}


void loop() {
  int tempVal = analogRead(TEMP_PIN);
  int tempSwitchState = digitalRead(MESSURMENT_SWITCH_PIN);

  float tempC = readTempC(tempVal);
  if (tempSwitchState == HIGH) {
    printTemp(tempC, "C");
    printTargetTemp(targetTemperatureInC, "C");
  } else {
    float tempF = readTempF(tempC);
    float targetTempF = readTempF(targetTemperatureInC);
    printTemp(tempF, "F");
    printTargetTemp(targetTempF, "F");
  }

  wifiIconAnimation();
  sendTempAfterDelay(tempC);
  showTime();
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

float readTempC(int val) {
  const float BETA = 3950;
  float analogValue = val * 0.004882814;
  float tempC = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 432.75;

  return tempC;
}

float readTempF(float tempC) {
  return (tempC - 32.0) / 1.8;
}


void sendTempAfterDelay(float tempC) {
  unsigned long currentTime = millis();
  if ((unsigned long)(currentTime - lastTime) >= timerDelay && WiFi.status() == WL_CONNECTED) {
    digitalWrite(LED_1_PIN, HIGH);
    char tempCChars[3];
    dtostrf(tempC, 3, 1, tempCChars);
    String tempCString = tempCChars;

    char tempFChars[3];
    dtostrf(readTempF(tempC), 3, 1, tempFChars);
    String tempFString = tempFChars;

    String body = "{\"data\": [{\"value\": \"" + tempCString +
                  "\", \"messurment\": \"C\"}, {\"value\": \"" + tempFString +
                  "\", \"messurment\": \"F\"}]}";

    HTTPClient http;
    http.useHTTP10(true);

    http.addHeader("Content-Type", "application/json");
    http.addHeader("Api-Token", "sImp0aSI6InBqcTNtODViMW9iYiJ9");
    Serial.println("Request send to: http://168.1.1.164:8081/api/temperature/" + deviceId);
    Serial.println("body: " + body);
    http.begin("http://localhost:8081/api/temperature/" + deviceId);
    http.POST(body);
    Serial.println("Request end...");
    http.end();
    lastTime = currentTime;
    delay(250);
    digitalWrite(LED_1_PIN, LOW);
  }
}

void wifiIconAnimation() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to WiFi...");
    LCD.setCursor(19, 0);
    LCD.write(byte(259));
    delay(200);
    LCD.setCursor(19, 0);
    LCD.write(byte(260));
    delay(200);
    LCD.setCursor(19, 0);
    LCD.write(byte(261));
    delay(200);
  }
}

void showTime() {
  LCD.setCursor(0, 3);
  LCD.write((byte)257);
  LCD.write((byte)258);
  DateTime now = RTC.now();
  LCD.print(now.hour(), DEC);
  LCD.print(':');
  LCD.print(now.minute(), DEC);
  LCD.print(':');
  LCD.print(now.second(), DEC);
  LCD.print("  ");
}

void printTemp(float temp, String messurment)
{
  char tempString[6] = "     ";
  dtostrf(temp, 3, 1, tempString);

  LCD.setCursor(0, 0);
  LCD.print("CURRENT ");
  LCD.write((byte)256);
  LCD.print(" ");
  LCD.print(tempString);
  LCD.print((char)223);
  LCD.print(messurment);
  LCD.print("  ");
}

void printTargetTemp(float temp, String messurment)
{
  char tempString[6] = "     ";
  dtostrf(temp, 3, 1, tempString);

  LCD.setCursor(0, 1);
  LCD.print("TARGET  ");
  LCD.write((byte)256);
  LCD.print(" ");
  LCD.print(tempString);
  LCD.print((char)223);
  LCD.print(messurment);
  LCD.print("  ");
}

void readEncoder() {
  int dtValue = digitalRead(ENCODER_DT_PIN);
  if (dtValue == HIGH) {
    ++targetTemperatureInC;
  }
  if (dtValue == LOW) {
    --targetTemperatureInC;
  }
}

void initLCD() {
  byte wifi1[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00100,};
  byte wifi2[8] = { B00000, B00000, B00000, B00000, B00100, B01010, B00000, B00100,};
  byte wifi3[8] = {B00000, B01110, B10001, B00000, B00100, B01010, B00000, B00100,};

  byte termometrc[8] = {B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110};

  byte clockChar1[] = { B00111, B01000, B10010, B10010, B10011, B10000, B01000, B00111};
  byte clockChar2[] = {B10000, B01000, B00100, B00100, B10100, B00100, B01000, B10000};

  LCD.init();
  LCD.backlight();
  LCD.createChar(259, wifi1);
  LCD.createChar(260, wifi2);
  LCD.createChar(261, wifi3);

  LCD.createChar(256, termometrc);

  LCD.createChar(257, clockChar1);
  LCD.createChar(258, clockChar2);
}

void initRTC() {
  if (!RTC.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }
}
$abcdeabcde151015202530fghijfghij
GND5VSDASCLSQWRTCDS1307+