#include <Wire.h>
#include "RTClib.h"
#include <TM1637Display.h>

// --- Deklarasi modul TM1637 untuk tampilan yang sudah ada ---
TM1637Display sevSeg1(2, 3);    // Jam dan menit (waktu RTC)
TM1637Display sevSeg2(4, 5);    // Detik
TM1637Display sevSeg3(6, 7);    // Tanggal dan bulan (dengan dash sebagai pemisah)
TM1637Display sevSeg4(8, 9);    // Tahun
TM1637Display sevSeg5(10, 11);  // Waktu sahur (jam+menit)
TM1637Display sevSeg6(12, 13);  // Hitungan mundur (jam+menit) ke sahur
TM1637Display sevSeg7(14, 15);  // Hitungan mundur detik ke sahur

TM1637Display sevSeg8(16, 17);   // Waktu imsyak (jam+menit)
TM1637Display sevSeg9(18, 19);   // Hitungan mundur (jam+menit) ke imsyak
TM1637Display sevSeg10(22, 23);  // Hitungan mundur detik ke imsyak

TM1637Display sevSeg11(24, 25);  // Waktu subuh (jam+menit)
TM1637Display sevSeg12(26, 27);  // Hitungan mundur (jam+menit) ke subuh
TM1637Display sevSeg13(28, 29);  // Hitungan mundur detik ke subuh

TM1637Display sevSeg14(30, 31);  // Waktu syuruq/terbit (jam+menit)
TM1637Display sevSeg15(32, 33);  // Hitungan mundur (jam+menit) ke syuruq/terbit
TM1637Display sevSeg16(34, 35);  // Hitungan mundur detik ke syuruq/terbit

// --- Deklarasi modul TM1637 untuk waktu baru ---
// Ishraq/Dhuha
TM1637Display sevSeg17(36, 37); // Tampilkan jam+menit waktu ishraq/dhuha
TM1637Display sevSeg18(38, 39); // Hitungan mundur (jam+menit) ke ishraq/dhuha
TM1637Display sevSeg19(40, 41); // Hitungan mundur detik ke ishraq/dhuha
// Dzuhur/Jumat
TM1637Display sevSeg20(42, 43); // Tampilkan jam+menit waktu dzuhur/jumat
TM1637Display sevSeg21(44, 45); // Hitungan mundur (jam+menit) ke dzuhur/jumat
TM1637Display sevSeg22(46, 47); // Hitungan mundur detik ke dzuhur/jumat
// Ashar
TM1637Display sevSeg23(48, 49); // Tampilkan jam+menit waktu ashar
TM1637Display sevSeg24(50, 51); // Hitungan mundur (jam+menit) ke ashar
TM1637Display sevSeg25(52, 53); // Hitungan mundur detik ke ashar
// Maghrib
TM1637Display sevSeg26(A0, A1); // Tampilkan jam+menit waktu maghrib
TM1637Display sevSeg27(A2, A3); // Hitungan mundur (jam+menit) ke maghrib
TM1637Display sevSeg28(A4, A5); // Hitungan mundur detik ke maghrib
// Isya
TM1637Display sevSeg29(A6, A7); // Tampilkan jam+menit waktu isya
TM1637Display sevSeg30(A8, A9); // Hitungan mundur (jam+menit) ke isya
TM1637Display sevSeg31(A10, A11); // Hitungan mundur detik ke isya
// Iqomah (durasi 11 menit)
// SevSeg32: hitungan mundur (jam+menit)
// SevSeg33: hitungan mundur detik
TM1637Display sevSeg32(A12, A13);
TM1637Display sevSeg33(A14, A15);

RTC_DS1307 rtc;

// --- Konstanta waktu untuk jadwal ---
// Waktu sahur, imsyak, subuh, dan syuruq sudah ada...
const int sahurHour = 3;
const int sahurMinute = 20;
const int imsyakHour = 4;    
const int imsyakMinute = 27;
const int subuhHour = 4;     
const int subuhMinute = 37;
const int syuruqHour = 5;    
const int syuruqMinute = 53;

// Tambahan waktu untuk waktu baru (ubah sesuai kebutuhan)
const int ishraqHour   = 6;   // contoh: 06:23 untuk ishraq/dhuha
const int ishraqMinute = 23;
const int dzuhurHour   = 12;  // contoh: 12:01 untuk dzuhur/jumat
const int dzuhurMinute = 1;
const int asharHour    = 15;  // contoh: 15:09 untuk ashar
const int asharMinute  = 9;
const int maghribHour  = 18;  // contoh: 18:04 untuk maghrib
const int maghribMinute= 4;
const int isyaHour     = 19;  // contoh: 19:11 untuk isya
const int isyaMinute   = 11;

// Durasi iqomah dalam detik (11 menit)
const int iqomahDuration = 11 * 60; // 540 detik

void setup() {
  Wire.begin();
  rtc.begin();

  // Jika RTC belum berjalan, set waktu berdasarkan waktu kompilasi
  if (!rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  
  // Atur kecerahan tiap modul (0x00 sampai 0x0f)
  sevSeg1.setBrightness(0x0f);
  sevSeg2.setBrightness(0x0f);
  sevSeg3.setBrightness(0x0f);
  sevSeg4.setBrightness(0x0f);
  sevSeg5.setBrightness(0x0f);
  sevSeg6.setBrightness(0x0f);
  sevSeg7.setBrightness(0x0f);
  sevSeg8.setBrightness(0x0f);
  sevSeg9.setBrightness(0x0f);
  sevSeg10.setBrightness(0x0f);
  sevSeg11.setBrightness(0x0f);
  sevSeg12.setBrightness(0x0f);
  sevSeg13.setBrightness(0x0f);
  sevSeg14.setBrightness(0x0f);
  sevSeg15.setBrightness(0x0f);
  sevSeg16.setBrightness(0x0f);
  
  sevSeg17.setBrightness(0x0f);
  sevSeg18.setBrightness(0x0f);
  sevSeg19.setBrightness(0x0f);
  sevSeg20.setBrightness(0x0f);
  sevSeg21.setBrightness(0x0f);
  sevSeg22.setBrightness(0x0f);
  sevSeg23.setBrightness(0x0f);
  sevSeg24.setBrightness(0x0f);
  sevSeg25.setBrightness(0x0f);
  sevSeg26.setBrightness(0x0f);
  sevSeg27.setBrightness(0x0f);
  sevSeg28.setBrightness(0x0f);
  sevSeg29.setBrightness(0x0f);
  sevSeg30.setBrightness(0x0f);
  sevSeg31.setBrightness(0x0f);
  sevSeg32.setBrightness(0x0f);
  sevSeg33.setBrightness(0x0f);
}

void loop() {
  DateTime now = rtc.now();
  unsigned long nowUnix = now.unixtime();

  // --- Cek apakah sudah waktunya alarm untuk salah satu jadwal ---
  // Untuk mencegah pemicu berulang dalam satu menit, gunakan flag dengan menyimpan menit terakhir yang terpicu.
  static int lastAlarmMinute = -1;
  // Gunakan kondisi saat detik kurang dari 10 sebagai jendela trigger
  if (now.second() < 10 && now.minute() != lastAlarmMinute) {
    if ((now.hour() == sahurHour && now.minute() == sahurMinute) ||
        (now.hour() == imsyakHour && now.minute() == imsyakMinute) ||
        (now.hour() == subuhHour && now.minute() == subuhMinute) ||
        (now.hour() == syuruqHour && now.minute() == syuruqMinute) ||
        (now.hour() == ishraqHour && now.minute() == ishraqMinute) ||
        (now.hour() == dzuhurHour && now.minute() == dzuhurMinute) ||
        (now.hour() == asharHour && now.minute() == asharMinute) ||
        (now.hour() == maghribHour && now.minute() == maghribMinute) ||
        (now.hour() == isyaHour && now.minute() == isyaMinute))
    {
      lastAlarmMinute = now.minute();

  }

  // === Tampilan Waktu RTC (sama seperti sebelumnya) ===
  int hh = now.hour();
  int mm = now.minute();
  int timeVal = hh * 100 + mm;
  bool colonState = (millis() / 500) % 2 == 0;  
  sevSeg1.showNumberDecEx(timeVal, colonState ? 0x40 : 0, true);
  
  int ss = now.second();
  sevSeg2.clear();
  sevSeg2.showNumberDec(ss, true, 2, 2);
  
  int dd = now.day();
  int mo = now.month();
  int dateVal = dd * 100 + mo;
  sevSeg3.showNumberDecEx(dateVal, 0x40, true);
  
  int yyyy = now.year();
  sevSeg4.showNumberDec(yyyy, true, 4, 0);
  
  // === Waktu Sahur ===
  DateTime sahurTime(now.year(), now.month(), now.day(), sahurHour, sahurMinute, 0);
  if (now >= sahurTime) {
    sahurTime = DateTime(sahurTime.year(), sahurTime.month(), sahurTime.day() + 1, sahurHour, sahurMinute, 0);
  }
  long totalSecondsSahur = sahurTime.unixtime() - nowUnix;
  int countdownH_Sahur = totalSecondsSahur / 3600;
  int countdownM_Sahur = (totalSecondsSahur % 3600) / 60;
  int countdownS_Sahur = totalSecondsSahur % 60;
  
  int sahurDisplay = sahurHour * 100 + sahurMinute;
  bool sahurColon = (now.hour() == sahurHour && now.minute() == sahurMinute) ? ((millis() / 500) % 2 == 0) : false;
  sevSeg5.showNumberDecEx(sahurDisplay, sahurColon ? 0x40 : 0, true);
  
  int countdownHM_Sahur = countdownH_Sahur * 100 + countdownM_Sahur;
  bool countdownColonSahur = (millis() / 500) % 2 == 0;
  sevSeg6.showNumberDecEx(countdownHM_Sahur, countdownColonSahur ? 0x40 : 0, true);
  
  sevSeg7.clear();
  sevSeg7.showNumberDec(countdownS_Sahur, true, 2, 2);
  
  // === Waktu Imsyak ===
  DateTime imsyakTime(now.year(), now.month(), now.day(), imsyakHour, imsyakMinute, 0);
  if (now >= imsyakTime) {
    imsyakTime = DateTime(imsyakTime.year(), imsyakTime.month(), imsyakTime.day() + 1, imsyakHour, imsyakMinute, 0);
  }
  long totalSecondsImsyak = imsyakTime.unixtime() - nowUnix;
  int countdownH_Imsyak = totalSecondsImsyak / 3600;
  int countdownM_Imsyak = (totalSecondsImsyak % 3600) / 60;
  int countdownS_Imsyak = totalSecondsImsyak % 60;
  
  int imsyakDisplay = imsyakHour * 100 + imsyakMinute;
  bool imsyakColon = (now.hour() == imsyakHour && now.minute() == imsyakMinute) ? ((millis() / 500) % 2 == 0) : false;
  sevSeg8.showNumberDecEx(imsyakDisplay, imsyakColon ? 0x40 : 0, true);
  
  int countdownHM_Imsyak = countdownH_Imsyak * 100 + countdownM_Imsyak;
  bool countdownColonImsyak = (millis() / 500) % 2 == 0;
  sevSeg9.showNumberDecEx(countdownHM_Imsyak, countdownColonImsyak ? 0x40 : 0, true);
  
  sevSeg10.clear();
  sevSeg10.showNumberDec(countdownS_Imsyak, true, 2, 2);
  
  // === Waktu Subuh ===
  DateTime subuhTime(now.year(), now.month(), now.day(), subuhHour, subuhMinute, 0);
  if (now >= subuhTime) {
    subuhTime = DateTime(subuhTime.year(), subuhTime.month(), subuhTime.day() + 1, subuhHour, subuhMinute, 0);
  }
  long totalSecondsSubuh = subuhTime.unixtime() - nowUnix;
  int countdownH_Subuh = totalSecondsSubuh / 3600;
  int countdownM_Subuh = (totalSecondsSubuh % 3600) / 60;
  int countdownS_Subuh = totalSecondsSubuh % 60;
  
  int subuhDisplay = subuhHour * 100 + subuhMinute;
  bool subuhColon = (now.hour() == subuhHour && now.minute() == subuhMinute) ? ((millis() / 500) % 2 == 0) : false;
  sevSeg11.showNumberDecEx(subuhDisplay, subuhColon ? 0x40 : 0, true);
  
  int countdownHM_Subuh = countdownH_Subuh * 100 + countdownM_Subuh;
  bool countdownColonSubuh = (millis() / 500) % 2 == 0;
  sevSeg12.showNumberDecEx(countdownHM_Subuh, countdownColonSubuh ? 0x40 : 0, true);
  
  sevSeg13.clear();
  sevSeg13.showNumberDec(countdownS_Subuh, true, 2, 2);
  
  // === Waktu Syuruq/Terbit ===
  DateTime syuruqTime(now.year(), now.month(), now.day(), syuruqHour, syuruqMinute, 0);
  if (now >= syuruqTime) {
    syuruqTime = DateTime(syuruqTime.year(), syuruqTime.month(), syuruqTime.day() + 1, syuruqHour, syuruqMinute, 0);
  }
  long totalSecondsSyuruq = syuruqTime.unixtime() - nowUnix;
  int countdownH_Syuruq = totalSecondsSyuruq / 3600;
  int countdownM_Syuruq = (totalSecondsSyuruq % 3600) / 60;
  int countdownS_Syuruq = totalSecondsSyuruq % 60;
  
  int syuruqDisplay = syuruqHour * 100 + syuruqMinute;
  bool syuruqColon = (now.hour() == syuruqHour && now.minute() == syuruqMinute) ? ((millis() / 500) % 2 == 0) : false;
  sevSeg14.showNumberDecEx(syuruqDisplay, syuruqColon ? 0x40 : 0, true);
  
  int countdownHM_Syuruq = countdownH_Syuruq * 100 + countdownM_Syuruq;
  bool countdownColonSyuruq = (millis() / 500) % 2 == 0;
  sevSeg15.showNumberDecEx(countdownHM_Syuruq, countdownColonSyuruq ? 0x40 : 0, true);
  
  sevSeg16.clear();
  sevSeg16.showNumberDec(countdownS_Syuruq, true, 2, 2);
  
  // === Waktu Baru (tanpa TimeSpan) ===
  auto getTargetUnix = [&](int hr, int mn) -> unsigned long {
    unsigned long t = DateTime(now.year(), now.month(), now.day(), hr, mn, 0).unixtime();
    if(nowUnix >= t) t += 86400UL;
    return t;
  };

  // --- Ishraq/Dhuha ---
  unsigned long targetIshraq = getTargetUnix(ishraqHour, ishraqMinute);
  unsigned long diffIshraq = targetIshraq - nowUnix;
  int ishraqCountH = diffIshraq / 3600;
  int ishraqCountM = (diffIshraq % 3600) / 60;
  int ishraqCountS = diffIshraq % 60;
  
  int ishraqDisplay = ishraqHour * 100 + ishraqMinute;
  bool ishraqColon = (now.hour() == ishraqHour && now.minute() == ishraqMinute) ? ((millis()/500)%2==0) : false;
  sevSeg17.showNumberDecEx(ishraqDisplay, ishraqColon ? 0x40 : 0, true);
  
  int countdownIshraqHM = ishraqCountH * 100 + ishraqCountM;
  bool countdownIshraqColon = (millis()/500)%2==0;
  sevSeg18.showNumberDecEx(countdownIshraqHM, countdownIshraqColon ? 0x40 : 0, true);
  
  sevSeg19.clear();
  sevSeg19.showNumberDec(ishraqCountS, true, 2, 2);
  
  // --- Dzuhur/Jumat ---
  unsigned long targetDzuhur = getTargetUnix(dzuhurHour, dzuhurMinute);
  unsigned long diffDzuhur = targetDzuhur - nowUnix;
  int dzuhurCountH = diffDzuhur / 3600;
  int dzuhurCountM = (diffDzuhur % 3600) / 60;
  int dzuhurCountS = diffDzuhur % 60;
  
  int dzuhurDisplay = dzuhurHour * 100 + dzuhurMinute;
  bool dzuhurColon = (now.hour() == dzuhurHour && now.minute() == dzuhurMinute) ? ((millis()/500)%2==0) : false;
  sevSeg20.showNumberDecEx(dzuhurDisplay, dzuhurColon ? 0x40 : 0, true);
  
  int countdownDzuhurHM = dzuhurCountH * 100 + dzuhurCountM;
  bool countdownDzuhurColon = (millis()/500)%2==0;
  sevSeg21.showNumberDecEx(countdownDzuhurHM, countdownDzuhurColon ? 0x40 : 0, true);
  
  sevSeg22.clear();
  sevSeg22.showNumberDec(dzuhurCountS, true, 2, 2);
  
  // --- Ashar ---
  unsigned long targetAshar = getTargetUnix(asharHour, asharMinute);
  unsigned long diffAshar = targetAshar - nowUnix;
  int asharCountH = diffAshar / 3600;
  int asharCountM = (diffAshar % 3600) / 60;
  int asharCountS = diffAshar % 60;
  
  int asharDisplay = asharHour * 100 + asharMinute;
  bool asharColon = (now.hour() == asharHour && now.minute() == asharMinute) ? ((millis()/500)%2==0) : false;
  sevSeg23.showNumberDecEx(asharDisplay, asharColon ? 0x40 : 0, true);
  
  int countdownAsharHM = asharCountH * 100 + asharCountM;
  bool countdownAsharColon = (millis()/500)%2==0;
  sevSeg24.showNumberDecEx(countdownAsharHM, countdownAsharColon ? 0x40 : 0, true);
  
  sevSeg25.clear();
  sevSeg25.showNumberDec(asharCountS, true, 2, 2);
  
  // --- Maghrib ---
  unsigned long targetMaghrib = getTargetUnix(maghribHour, maghribMinute);
  unsigned long diffMaghrib = targetMaghrib - nowUnix;
  int maghribCountH = diffMaghrib / 3600;
  int maghribCountM = (diffMaghrib % 3600) / 60;
  int maghribCountS = diffMaghrib % 60;
  
  int maghribDisplay = maghribHour * 100 + maghribMinute;
  bool maghribColon = (now.hour() == maghribHour && now.minute() == maghribMinute) ? ((millis()/500)%2==0) : false;
  sevSeg26.showNumberDecEx(maghribDisplay, maghribColon ? 0x40 : 0, true);
  
  int countdownMaghribHM = maghribCountH * 100 + maghribCountM;
  bool countdownMaghribColon = (millis()/500)%2==0;
  sevSeg27.showNumberDecEx(countdownMaghribHM, countdownMaghribColon ? 0x40 : 0, true);
  
  sevSeg28.clear();
  sevSeg28.showNumberDec(maghribCountS, true, 2, 2);
  
  // --- Isya ---
  unsigned long targetIsya = getTargetUnix(isyaHour, isyaMinute);
  unsigned long diffIsya = targetIsya - nowUnix;
  int isyaCountH = diffIsya / 3600;
  int isyaCountM = (diffIsya % 3600) / 60;
  int isyaCountS = diffIsya % 60;
  
  int isyaDisplay = isyaHour * 100 + isyaMinute;
  bool isyaColon = (now.hour() == isyaHour && now.minute() == isyaMinute) ? ((millis()/500)%2==0) : false;
  sevSeg29.showNumberDecEx(isyaDisplay, isyaColon ? 0x40 : 0, true);
  
  int countdownIsyaHM = isyaCountH * 100 + isyaCountM;
  bool countdownIsyaColon = (millis()/500)%2==0;
  sevSeg30.showNumberDecEx(countdownIsyaHM, countdownIsyaColon ? 0x40 : 0, true);
  
  sevSeg31.clear();
  sevSeg31.showNumberDec(isyaCountS, true, 2, 2);
  
  // --- Iqomah (9 menit countdown) ---  
  int iqomahDiff = -1; // jika aktif, selisih detik menuju akhir periode iqomah
  unsigned long subuhScheduled = DateTime(now.year(), now.month(), now.day(), subuhHour, subuhMinute, 0).unixtime();
  if(nowUnix >= subuhScheduled && nowUnix < subuhScheduled + iqomahDuration) {
    iqomahDiff = (subuhScheduled + iqomahDuration) - nowUnix;
  }
  unsigned long dzuhurScheduled = DateTime(now.year(), now.month(), now.day(), dzuhurHour, dzuhurMinute, 0).unixtime();
  if(iqomahDiff < 0 && nowUnix >= dzuhurScheduled && nowUnix < dzuhurScheduled + iqomahDuration) {
    iqomahDiff = (dzuhurScheduled + iqomahDuration) - nowUnix;
  }
  unsigned long asharScheduled = DateTime(now.year(), now.month(), now.day(), asharHour, asharMinute, 0).unixtime();
  if(iqomahDiff < 0 && nowUnix >= asharScheduled && nowUnix < asharScheduled + iqomahDuration) {
    iqomahDiff = (asharScheduled + iqomahDuration) - nowUnix;
  }
  unsigned long maghribScheduled = DateTime(now.year(), now.month(), now.day(), maghribHour, maghribMinute, 0).unixtime();
  if(iqomahDiff < 0 && nowUnix >= maghribScheduled && nowUnix < maghribScheduled + iqomahDuration) {
    iqomahDiff = (maghribScheduled + iqomahDuration) - nowUnix;
  }
  unsigned long isyaScheduled = DateTime(now.year(), now.month(), now.day(), isyaHour, isyaMinute, 0).unixtime();
  if(iqomahDiff < 0 && nowUnix >= isyaScheduled && nowUnix < isyaScheduled + iqomahDuration) {
    iqomahDiff = (isyaScheduled + iqomahDuration) - nowUnix;
  }
  
  if(iqomahDiff >= 0) {
    int iqomahCountH = iqomahDiff / 3600;
    int iqomahCountM = (iqomahDiff % 3600) / 60;
    int iqomahCountS = iqomahDiff % 60;
    int iqomahHM = iqomahCountH * 100 + iqomahCountM;
    bool iqomahBlink = (iqomahDiff <= 5) ? ((millis()/500)%2==0) : false;
    sevSeg32.showNumberDecEx(iqomahHM, iqomahBlink ? 0x40 : 0, true);
    sevSeg33.clear();
    sevSeg33.showNumberDec(iqomahCountS, true, 2, 2);
  } else {
    sevSeg32.clear();
    sevSeg33.clear();
  }
  
  delay(100);
  }
}
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
GND5VSDASCLSQWRTCDS1307+
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display
4-Digit Display