#include <Arduino.h>
#include "Arduino_GFX_Library.h"
#include "pin_config.h"
#include "SensorPCF85063.hpp"
#include <Wire.h>

#include "HWCDC.h"

#define BUTTON_PIN 0
HWCDC USBSerial;

SensorPCF85063 rtc;
bool isPaused = false;
int timerP = -1;
int MAX_TIMER = 1 * 60;
uint8_t globalTextSize = 6;
uint32_t lastMillis;
char previousTimeString[20] = "";
Arduino_DataBus *bus = new Arduino_ESP32SPI(LCD_DC, LCD_CS, LCD_SCK, LCD_MOSI);

Arduino_GFX *gfx = new Arduino_ST7789(bus, LCD_RST /* RST */,
                                      0 /* rotation */, true /* IPS */, LCD_WIDTH, LCD_HEIGHT, 0, 20, 0, 0);

int16_t getCenteredX(const char *text, uint8_t textSize) {
  int16_t textWidth = strlen(text) * 6 * textSize;  // 6 pixels per character in default size
  return (LCD_WIDTH - textWidth) / 2;
}

void updateColorsWithPercentage(double percentage, uint16_t width, uint16_t height) {
  uint16_t fillHeight = height / 20 - 1;
  uint16_t curY = fillHeight;
  double perTesting = 0.95;

  for (int i = 0; i < 5; i++) {
    if (percentage > perTesting) {
      gfx->fillRect(0, curY, width, fillHeight, GREEN);
    }
    else  {
      gfx->fillRect(0, curY, width, fillHeight, BLACK);
    }
    perTesting -= 0.05;
    curY += fillHeight;
  }
  for (int i = 0; i < 5; i++) {
    if (percentage > perTesting) {
      gfx->fillRect(0, curY, width, fillHeight, YELLOW);
    }
    else  {
      gfx->fillRect(0, curY, width, fillHeight, BLACK);
    }
    perTesting -= 0.05;
    curY += fillHeight;
  }
  for (int i = 0; i < 5; i++) {
    if (percentage > perTesting) {
      gfx->fillRect(0, curY, width, fillHeight, ORANGE);
    }
    else  {
      gfx->fillRect(0, curY, width, fillHeight, BLACK);
    }
    perTesting -= 0.05;
    curY += fillHeight;
  }
  for (int i = 0; i < 5; i++) {
    if (percentage > perTesting) {
      gfx->fillRect(0, curY, width, fillHeight, RED);
    }
    else  {
      gfx->fillRect(0, curY, width, fillHeight, BLACK);
    }
    perTesting -= 0.05;
    curY += fillHeight;
  }
  if (percentage == 0.0)
  gfx->fillScreen(BLACK);
}

void setup() {
  USBSerial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  gfx->begin();
  gfx->fillScreen(BLACK);
  pinMode(LCD_BL, OUTPUT);
  digitalWrite(LCD_BL, HIGH);

  gfx->fillRect(40, 120, 160, 70, BLACK);  // Clear the area for the time
  gfx->setTextColor(WHITE);
  gfx->setTextSize(globalTextSize, globalTextSize, 0);

  int16_t timeX = getCenteredX("100%", globalTextSize);
  gfx->setCursor(timeX, 134);  // Adjust Y-coordinate as needed
  gfx->println("100%");  // Display the new time
  if (!rtc.begin(Wire, PCF85063_SLAVE_ADDRESS, IIC_SDA, IIC_SCL)) {
    USBSerial.println("Failed to find PCF8563 - check your wiring!");
    while (1) {
      delay(1000);
    }
  }
}

void loop() {
  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState == LOW) {
    while (buttonState == LOW) { buttonState = digitalRead(BUTTON_PIN); }
    bool keepgoing = true;

    int timer = -1;
    gfx->begin();
    gfx->fillScreen(BLACK);
    pinMode(LCD_BL, OUTPUT);
    digitalWrite(LCD_BL, HIGH);

    while (keepgoing) {
      buttonState = digitalRead(BUTTON_PIN);

      if (buttonState == LOW) {
        while (buttonState == LOW) {
          buttonState = digitalRead(BUTTON_PIN);
        }

        if (!isPaused) {
          timerP = timer;
        }
        isPaused = !isPaused;
      }

      if (millis() - lastMillis > 1000) {
        lastMillis = millis();
        if (!isPaused) {
          timer++;
        }
        // Format the current time as a string
        char timeString[20];

        double percentValue;
        if (isPaused) {
          percentValue = 1.0 - (static_cast<double>(timerP) / static_cast<double>(MAX_TIMER));
          sprintf(timeString, "%d%%", static_cast<int>(percentValue * 100));
        } else {
          percentValue = 1.0 - (static_cast<double>(timer) / static_cast<double>(MAX_TIMER));
          sprintf(timeString, "%d%%", static_cast<int>(percentValue * 100));
          if (timer == MAX_TIMER) {
            keepgoing = false;
          }
        }



        // Only update the time if it has changed
        if (strcmp(timeString, previousTimeString) != 0) {
          updateColorsWithPercentage(percentValue, LCD_WIDTH, LCD_HEIGHT);
          gfx->fillRect(40, 120, 160, 70, BLACK);
          // Clear the previous time area by filling a small rectangle
          // gfx->fillRect(0, 134, LCD_WIDTH, 50, BLACK);  // Clear the area for the time
          gfx->setTextColor(WHITE);
          gfx->setTextSize(globalTextSize, globalTextSize, 0);

          int16_t timeX = getCenteredX(timeString, globalTextSize);
          gfx->setCursor(timeX, 134);  // Adjust Y-coordinate as needed
          gfx->println(timeString);    // Display the new time

          // Save the current time as the previous time
          strcpy(previousTimeString, timeString);
        }
      }
    }
  }
}
