#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
// Define TFT pins
#define TFT_CS    5
#define TFT_RST   4
#define TFT_DC    2
#define TFT_SCLK  18
#define TFT_MOSI  23
#define PIN 19

const char* ssid     = "Robot-idk";
const char* password = "acdd238414";

String city = "Fremont";
String apiKey = "e710429c6e7e93d10846402cafa5739e";


const char* apikey = "60d6195b3f4745589205939e3758abc6";  // Replace with your real key
const char* stockSymbol = "AAPL";


// Initialize the display object
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // update every minute

// Forward declare the functions

int COLOR_WHITE = ST77XX_WHITE;
int COLOR_BLACK = ST77XX_BLACK;

// States
int demo_mode = 1;
int current_animation_index = 0;

int ref_left_eye = 32;
int ref_eye_height = 40;
int ref_eye_width = 40;
int ref_space_between_eye = 10;
int ref_corner_radius = 10;

int left_eye_height = ref_eye_height;
int left_eye_width = ref_eye_width;
int left_eye_x = ref_left_eye;
int left_eye_y = ref_left_eye;
int right_eye_x = ref_left_eye + ref_eye_width + ref_space_between_eye;
int right_eye_y = ref_left_eye;
int right_eye_height = ref_eye_height;
int right_eye_width = ref_eye_width;
int corner_radius = ref_corner_radius;

int SCREEN_WIDTH = 240;
int SCREEN_HEIGHT = 240;
int count = 0;
String status = "";






void display_clearDisplay() {
  tft.fillScreen(COLOR_BLACK);
}

void display_fillRoundRect(int x, int y, int w, int h, int r, uint16_t color) {
  tft.fillRoundRect(x, y, w, h, r, color);
}

void display_fillTriangle(int x0,int y0, int x1,int y1,int x2,int y2, uint16_t color) {
  tft.fillTriangle(x0, y0, x1, y1, x2, y2, color);
}

void draw_eyes(bool update = true) {
  display_clearDisplay();
  int x = left_eye_x - left_eye_width / 2;
  int y = left_eye_y - left_eye_height / 2;
  display_fillRoundRect(x, y, left_eye_width, left_eye_height, corner_radius, COLOR_WHITE);
  x = right_eye_x - right_eye_width / 2;
  y = right_eye_y - right_eye_height / 2;
  display_fillRoundRect(x, y, right_eye_width, right_eye_height, corner_radius, COLOR_WHITE);
}

void reset_eyes(bool update = true) {
  left_eye_height = ref_eye_height;
  left_eye_width = ref_eye_width;
  right_eye_height = ref_eye_height;
  right_eye_width = ref_eye_width;

  left_eye_x = SCREEN_WIDTH / 2 - ref_eye_width / 2 - ref_space_between_eye / 2;
  left_eye_y = SCREEN_HEIGHT / 2;
  right_eye_x = SCREEN_WIDTH / 2 + ref_eye_width / 2 + ref_space_between_eye / 2;
  right_eye_y = SCREEN_HEIGHT / 2;

  corner_radius = ref_corner_radius;
  draw_eyes(update);
}

void blink(int speed = 1) {
  reset_eyes(false);
  draw_eyes();

  for (int i = 0; i < 3; i++) {
    left_eye_height -= speed;
    right_eye_height -= speed;
    left_eye_width += 3;
    right_eye_width += 3;
    draw_eyes();
    delay(1);
  }
  for (int i = 0; i < 3; i++) {
    left_eye_height += speed;
    right_eye_height += speed;
    left_eye_width -= 3;
    right_eye_width -= 3;
    draw_eyes();
    delay(1);
  }
}

void sleep() {
  reset_eyes(false);
  left_eye_height = 2;
  left_eye_width = ref_eye_width;
  right_eye_height = 2;
  right_eye_width = ref_eye_width;
  corner_radius = 0;
  draw_eyes(true);
}

void wakeup() {
  reset_eyes(false);
  sleep();
  for (int h = 2; h <= ref_eye_height; h += 2) {
    left_eye_height = h;
    right_eye_height = h;
    corner_radius = min(h, ref_corner_radius);
    draw_eyes(true);
  }
}


void getWeatherData() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&appid=" + apiKey + "&units=metric";
    http.begin(url);
    int httpCode = http.GET();

    if (httpCode == 200) {
      String payload = http.getString();
      Serial.println(payload);

      DynamicJsonDocument doc(1024);
      deserializeJson(doc, payload);

      float temp = doc["main"]["temp"];
      const char* weather = doc["weather"][0]["main"];

      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(10, 30);
      tft.print("City: "); tft.print(city);
      tft.setCursor(10, 70);
      tft.print("Temp: "); tft.print(temp); tft.println(" C");
      tft.setCursor(10, 110);
      tft.print("Condition: "); tft.print(weather);
    } else {
      Serial.println("Failed to retrieve data.");
    }
    http.end();
  }
}

void time() {
  timeClient.update();
  unsigned long epochTime = timeClient.getEpochTime();

  int currentDay = day(epochTime);
  int currentMonth = month(epochTime);
  int currentYear = year(epochTime);

  tft.setCursor(10, 200);
  tft.setTextSize(2);
  tft.setTextColor(ST77XX_WHITE);
  tft.print("Date: ");
  tft.print(currentMonth);
  tft.print("/");
  tft.print(currentDay);
  tft.print("/");
  tft.print(currentYear);

}


void getStockPrice() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = "https://api.twelvedata.com/price?symbol=" + String(stockSymbol) + "&apikey=" + apikey;
    http.begin(url);
    int httpCode = http.GET();

    if (httpCode > 0) {
      String payload = http.getString();
      Serial.println("Received: " + payload);

      StaticJsonDocument<200> doc;
      DeserializationError error = deserializeJson(doc, payload);

      if (!error) {
        String price = doc["price"];
        tft.setCursor(20, 20);
        tft.setTextColor(ST77XX_GREEN);
        tft.print(stockSymbol + String(": $") + price);
        // You can now display price on your screen here
      } else {
        tft.print("JSON Parse Error");
      }
    } else {
      tft.print("HTTP GET Failed");
    }

    http.end();
  }
}




void loop() {
  if (digitalRead(PIN) == LOW){
    delay(500);
    count++;
    
  }
  else if (count == 1) {
    delay(1000);
    display_clearDisplay();
    getWeatherData();

  }
  else if (count == 2) {
    delay(1000);
    display_clearDisplay();
    time();
  }
  else if (count == 3) {
    delay(1000);
    display_clearDisplay();
    getStockPrice();
  }
  if (count >= 4) {
    display_clearDisplay();
    draw_eyes();
    count = 0;
  }
}









void setup() {
  WiFi.begin(ssid, password);
  tft.init(240, 240);   
  pinMode(PIN, INPUT_PULLUP);
  tft.setRotation(0);             // Rotate display if needed
  tft.fillScreen(ST77XX_BLACK);   // Background
  sleep();
  delay(2000);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);
  tft.setCursor(10, 10);
  tft.print("Duck1405");
  delay(3000);
  
  draw_eyes();
  delay(5000);
  blink();
  delay(5000);
  blink();


  display_clearDisplay();
  tft.setCursor(10, 10);
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  draw_eyes();
  tft.print("Hi, I am Bloop!!");






}



