#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <ThingSpeak.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int potpin = 34;
int heartValue = 0;
int graphX = 0;
int lastGraphX = 0;
int lastGraphY = 0;
bool pulseReading = false; // Variable to control reading
bool thingSpeakConnected = false; // Flag to indicate ThingSpeak connection status

const int buttonPin1 = 15; // GPIO pin for Button 1 (Start/Stop ECG)
const int buttonPin2 = 13; // GPIO pin for Button 2 (Start/Stop ThingSpeak)

// Wi-Fi and ThingSpeak configuration
const char* ssid = "Wokwi-GUEST"; // Your Wi-Fi SSID
const char* password = ""; // Your Wi-Fi password
const char* thingSpeakApiKey = "T8XYZEEPHBYI5FY4"; // Your ThingSpeak API Key
unsigned long thingSpeakChannelID = 2316140; // Your ThingSpeak Channel ID

WiFiClient client;

unsigned long wifiConnectStartTime = 0;
unsigned long thingSpeakConnectStartTime = 0;
bool wifiConnected = false;
bool wifiConnecting = false;
bool thingSpeakConnecting = false;
bool wifiDotVisible = false;
bool thingSpeakDotVisible = false;

bool uploadToThingSpeak(int value);

void setup() {
  Serial.begin(115200);
  pinMode(buttonPin1, INPUT_PULLUP); // Configure Button 1 pin as an input with a pull-up resistor
  pinMode(buttonPin2, INPUT_PULLUP); // Configure Button 2 pin as an input with a pull-up resistor

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C, OLED_RESET)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;) {
      // Add any necessary error handling here.
    }
  }
  display.clearDisplay();
  display.display();

  // Connect to Wi-Fi in the background
  WiFi.begin(ssid, password);
  wifiConnectStartTime = millis();
  wifiConnecting = true;
}

void loop() {
  // Check if Button 1 is pressed to toggle ECG reading
  if (digitalRead(buttonPin1) == LOW) {
    if (pulseReading) {
      pulseReading = false;
      display.setCursor(0, 20);
      display.print("ECG: Stopped        ");
    } else {
      pulseReading = true;
      display.setCursor(0, 20);
      display.print("ECG: Reading        ");
    }
    delay(1000); // Long-press delay to avoid repeated toggles
  }

  // Check WiFi connection status
  if (wifiConnecting) {
    if (WiFi.status() == WL_CONNECTED) {
      wifiConnected = true;
      wifiConnecting = false;
      wifiConnectStartTime = 0;
    } else {
      if (millis() - wifiConnectStartTime >= 500) {
        wifiConnectStartTime = millis();
        wifiDotVisible = !wifiDotVisible;
        display.drawPixel(120, 0, wifiDotVisible ? SSD1306_WHITE : SSD1306_BLACK);
      }
    }
  }

  // Check if WiFi is connected before attempting ThingSpeak connection
  if (wifiConnected && !thingSpeakConnected && !thingSpeakConnecting) {
    display.setCursor(0, 10);
    display.print("ThingSpeak: Connecting");
    display.display();

    ThingSpeak.begin(client);
    thingSpeakConnecting = true;
    thingSpeakConnectStartTime = millis();
  }

  // Check ThingSpeak connection status
  if (thingSpeakConnecting) {
    if (millis() - thingSpeakConnectStartTime >= 10000) {
      thingSpeakConnectStartTime = millis();
      if (uploadToThingSpeak(heartValue)) {
        thingSpeakConnected = true;
        thingSpeakConnecting = false;
      }
    }
  }

  // Handle ECG data and display
  if (pulseReading) {
    heartValue = analogRead(potpin);
    // Update the ECG graph and display as before
    // (Omitted for brevity)
  }

  // Display the BPM (heart rate) on the OLED
  display.setCursor(0, 30);
  display.print("BPM: ");  // Label for BPM
  display.print(heartValue);

  // Set text size for ECG graph
  display.setTextSize(1);

  // Update the ECG graph
  int graphHeight = map(heartValue, 0, 1023, 0, SCREEN_HEIGHT - 1);
  int graphY = SCREEN_HEIGHT - graphHeight;

  display.drawLine(lastGraphX, lastGraphY, graphX, graphY, SSD1306_WHITE);
  lastGraphX = graphX;
  lastGraphY = graphY;

  graphX++;
  if (graphX >= SCREEN_WIDTH) {
    graphX = 0;
    lastGraphX = 0;
    lastGraphY = 0; // Reset lastGraphY
    display.clearDisplay();
  }

  // Display a pulsing heart icon
  display.setCursor(60, 50);
  display.print("<3");

  // Update the display
  display.display();
  delay(10);  // You can adjust the delay to control the refresh rate
}

bool uploadToThingSpeak(int value) {
  return ThingSpeak.writeField(thingSpeakChannelID, 1, value, thingSpeakApiKey);
}