#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>

Adafruit_SSD1306 display(128, 64, &Wire, 4);
RTC_DS3231 rtc;

int hours, minutes, seconds;
#define YELLOW_ZONE 16

void TCA9548A(uint8_t bus)
{
  Wire.beginTransmission(0x70);
  Wire.write(1 << bus);
  Wire.endTransmission();
}

void setup()
{
  // Initialize RTC on channel 1
  TCA9548A(1);
  rtc.begin();
  
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

    // --- OPTIONAL MANUAL TIME SET (only enable when needed) ---
  // To set time manually, remove the comment marks from the lines below,
  // adjust the DateTime parameters (Year, Month, Day, Hour, Minute, Second),
  // upload once, then comment them out again to prevent overwriting the RTC each boot.
 
 // rtc.adjust(DateTime(2025, 10, 22, 12, 15, 00));  // YYYY, MM, DD, HH, MM, SS
 

  // Initialize displays with rotated orientation
  // Display 1: Seconds (leftmost) - Channel 2
  TCA9548A(2);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setRotation(1); // Rotate 90 degrees for portrait mode
  display.clearDisplay();
  display.display();

  // Display 2: Minutes (middle) - Channel 3
  TCA9548A(3);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setRotation(1); // Rotate 90 degrees for portrait mode
  display.clearDisplay();
  display.display();
  
  // Display 3: Hours (rightmost) - Channel 4
  TCA9548A(4);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setRotation(1); // Rotate 90 degrees for portrait mode
  display.clearDisplay();
  display.display();

   delay(500);
  showIntro();
  
 // delay(1000);
}

void showIntro() {
  int screenH = 128;
  const char* words[3] = {"CLOCK", "DISPL", "THREE"};

  // --- STEP 1: Loading animation + falling letters ---
  for (int h = 0; h <= 120; h += 6) {
    for (int idx = 0; idx < 3; idx++) {
      int ch = 2 + idx;
      TCA9548A(ch);
      display.clearDisplay();

      // --- Yellow frame (16x128, 2-px border) ---
      for (int i = 0; i < 2; i++) {
        display.drawRect(i, i, YELLOW_ZONE - 2 * i, screenH - 2 * i, WHITE);
      }

      // --- Filling bar ---
      int fillX = 4;
      int fillW = YELLOW_ZONE - 8;
      int fillY = 124 - h;
      display.fillRect(fillX, fillY, fillW, h, WHITE);

      // --- Falling letters ---
      display.setTextColor(WHITE);
      display.setTextSize(2);
      int textX = YELLOW_ZONE + 20;
      int textY = 12;
      const char* w = words[idx];

      // Determine how many letters to show depending on progress
      int totalLetters = strlen(w);
      int visibleLetters = map(h, 0, 120, 0, totalLetters);
      if (visibleLetters > totalLetters) visibleLetters = totalLetters;

      // Draw visible letters vertically, one by one
      for (int k = 0; k < visibleLetters; k++) {
        display.setCursor(textX, textY + k * 20);
        display.write(w[k]);
      }

      display.display();
    }
    delay(80);
  }

  delay(1000); // pause 1 s at full bar

  // --- STEP 2: Fade-out animation (bars emptying downward) ---
  for (int h = 120; h >= 0; h -= 6) {
    for (int idx = 0; idx < 3; idx++) {
      int ch = 2 + idx;
      TCA9548A(ch);
      display.clearDisplay();

      // --- Yellow frame ---
      for (int i = 0; i < 2; i++) {
        display.drawRect(i, i, YELLOW_ZONE - 2 * i, screenH - 2 * i, WHITE);
      }

      // --- Emptying bar ---
      int fillX = 4;
      int fillW = YELLOW_ZONE - 8;
      int fillY = 124 - h;
      display.fillRect(fillX, fillY, fillW, h, WHITE);

      // --- Keep all letters visible during fade ---
      display.setTextColor(WHITE);
      display.setTextSize(2);
      int textX = YELLOW_ZONE + 20;
      int textY = 12;
      const char* w = words[idx];
      for (int k = 0; w[k]; k++) {
        display.setCursor(textX, textY + k * 20);
        display.write(w[k]);
      }

      display.display();
    }
    delay(60);
  }

  // --- STEP 3: Clear all displays ---
  for (int ch = 2; ch <= 4; ch++) {
    TCA9548A(ch);
    display.clearDisplay();
    display.display();
  }
}

void loop()
{
  // Read time from RTC
  TCA9548A(1);
  DateTime now = rtc.now();
  hours = now.hour();
  minutes = now.minute();
  seconds = now.second();

  // Update Seconds Display (Left) - Channel 2
  TCA9548A(2);
  display.clearDisplay();
  drawDisplay(seconds, 'S', 60, seconds);
  display.display();

  // Update Minute Display (Middle) - Channel 3
  TCA9548A(3);
  display.clearDisplay();
  drawDisplay(minutes, 'M', 60, minutes);
  display.display();
  
  // Update Hours Display (Right) - Channel 4
  TCA9548A(4);
  display.clearDisplay();
  drawDisplay(hours, 'H', 24, hours);
  display.display();
  
  delay(200); // Update 5 times per second
}

void drawDisplay(int value, char unit, int maxValue, int barValue) {
  // NOTE: In portrait rotation, display.width() = 64, display.height() = 128
  int screenW = 64;
  int screenH = 128;

  // --- Bargraph container ---
  int barX = 0;
  int barW = YELLOW_ZONE;  // 16 px
  int barY = 0;
  int barH = screenH;

  // Outer rectangle (frame, 2-px thick)
  for (int i = 0; i < 2; i++) {
    display.drawRect(barX + i, barY + i, barW - 2 * i, barH - 2 * i, WHITE);
  }

  // --- Calculate bar height (usable area = 120 px: from y=4 to y=124) ---
  int innerTop = 4;
  int innerBottom = screenH - 4;
  int usableHeight = innerBottom - innerTop;  // 120 px

  int barHeight = map(barValue, 0, maxValue, 0, usableHeight);

  // --- Fill the bar inside the container ---
  int fillX = barX + 2 + 2;        // 2-px frame + 2-px gap
  int fillW = barW - 8;            // 2+2 margin each side → 8 total
  int fillY = innerBottom - barHeight;  // fill upward from bottom
  display.fillRect(fillX, fillY, fillW, barHeight, WHITE);

  // --- Blue field dimensions (right side) ---
  int frameX1 = YELLOW_ZONE;                
  int frameW  = screenW - YELLOW_ZONE;      
  int frameY1 = 0;
  int frameH  = screenH;

  // --- Outer frame (3 px) ---
  for (int i = 0; i < 3; i++) {
    display.drawRect(frameX1 + i, frameY1 + i, frameW - 2 * i, frameH - 2 * i, WHITE);
  }

  // --- Divider between letter and digits ---
  int dividerY = 40;  
  display.fillRect(frameX1 + 3, dividerY, frameW - 6, 3, WHITE);

  // --- Text ---
  display.setTextColor(WHITE);
  display.setTextSize(3);

  // Upper: unit letter (H / M / S)
  int unitX = frameX1 + 17;
  int unitY = 11;
  display.setCursor(unitX, unitY);
  display.print(unit);

  display.setTextSize(4);

  // Lower: digits
  int tens = value / 10;
  int units = value % 10;

  int tensX = frameX1 + 13;
  int tensY = 52;
  display.setCursor(tensX, tensY);
  display.print(tens);

  int unitsX = frameX1 + 13;
  int unitsY = 87;
  display.setCursor(unitsX, unitsY);
  display.print(units);

  // --- Inner rounded frames ---
  // Top rectangle (letters)
  int innerTopX = frameX1 + 4;
  int innerTopY = 4;
  int innerTopW = frameW - 8;
  int innerTopH = dividerY - innerTopY - 2; // 1px gap to divider
  for (int i = 0; i < 2; i++) {
    display.drawRoundRect(innerTopX + i, innerTopY + i, innerTopW - 2 * i, innerTopH - 2 * i, 4, WHITE);
  }

  // Bottom rectangle (digits)
  int innerBotX = frameX1 + 4;
  int innerBotY = dividerY + 4; // 1px gap below divider
  int innerBotW = frameW - 8;
  int innerBotH = frameH - innerBotY - 4;
  for (int i = 0; i < 2; i++) {
    display.drawRoundRect(innerBotX + i, innerBotY + i, innerBotW - 2 * i, innerBotH - 2 * i, 4, WHITE);
  }
}


