#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

// GPIOs where the NTC thermistors are connected
const int ntcPins[4] = {32, 33, 34, 35};

// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";

// Google Sheets API details
const char* google_script_id = "AKfycbzqP-j1L4cLd2TkbbbYWMGUI7_q09IZqja56CQ9RQrjCrRYBax08MNN2u6101fmSKAPSA";

// Constants for the NTC thermistor and resistor
const float nominalResistance = 10000; // 10kΩ resistor
const float nominalTemperature = 25;   // Nominal temperature for the thermistor
const float bCoefficient = 3950;       // Beta coefficient of the thermistor
const float seriesResistor = 10000;    // Value of the series resistor

// ILI9341 screen settings
#define TFT_CS     15
#define TFT_RST    4
#define TFT_DC     2
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

// Timing variables
unsigned long previousMillis = 0;
const long interval = 10000; // Interval for sending data to Google Sheets (10 seconds)

void setup() {
  // Start the Serial Monitor
  Serial.begin(115200);

  // Initialize ILI9341 display
  tft.begin();
  tft.setRotation(3); // Set the rotation as needed
  tft.fillScreen(ILI9341_BLACK);

  // Connect to WiFi
  connectToWiFi();
}

void loop() {
  // Update the display
  displayMenu();

  // Handle timing for sending data to Google Sheets
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Prepare the data to be sent
    String data = prepareData();

    // Send data to Google Sheets
    sendToGoogleSheets(data);
  }

  // Update WiFi status indicator
  updateWiFiStatus();
}

void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

String prepareData() {
  String data = "timestamp=" + String(millis()) + "&";

  for (int i = 0; i < 4; i++) {
    float temperatureC = readTemperature(ntcPins[i]);
    if (isnan(temperatureC)) {
      Serial.print("Error: Could not read temperature data from sensor ");
      Serial.println(i + 1);
      data += "sensor" + String(i + 1) + "=Error&";
    } else {
      data += "sensor" + String(i + 1) + "=" + String(temperatureC) + "&";
    }
  }

  // Remove the last '&'
  data.remove(data.length() - 1);

  return data;
}

float readTemperature(int pin) {
  int adcValue = analogRead(pin);
  float resistance = seriesResistor / ((4095.0 / adcValue) - 1);
  float steinhart;
  steinhart = resistance / nominalResistance;           // (R/Ro)
  steinhart = log(steinhart);                           // ln(R/Ro)
  steinhart /= bCoefficient;                            // 1/B * ln(R/Ro)
  steinhart += 1.0 / (nominalTemperature + 273.15);     // + (1/To)
  steinhart = 1.0 / steinhart;                          // Invert
  steinhart -= 273.15;                                  // Convert to Celsius

  return steinhart;
}

void displayMenu() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(10, 10);
  tft.println("Temperature Monitor");

  for (int i = 0; i < 4; i++) {
    float temperatureC = readTemperature(ntcPins[i]);
    tft.setCursor(10, 40 + (i * 30));
    tft.print("Sensor ");
    tft.print(i + 1);
    tft.print(": ");
    if (isnan(temperatureC)) {
      tft.println("Error");
    } else {
      tft.print(temperatureC);
      tft.println(" C");
    }
  }
}

void updateWiFiStatus() {
  tft.fillRect(200, 10, 10, 10, (WiFi.status() == WL_CONNECTED) ? ILI9341_GREEN : ILI9341_RED);
}

void sendToGoogleSheets(const String& data) {
  WiFiClientSecure client;
  HTTPClient http;

  client.setInsecure();
  String url = String("https://script.google.com/macros/s/") + google_script_id + "/exec?" + data;

  http.begin(client, url);
  int httpCode = http.GET();

  if (httpCode > 0) {
    Serial.println("Data sent successfully");
  } else {
    Serial.println("Error in sending data: " + String(httpCode));
  }

  http.end();
}