// =======================================================================
// ARDUINO LOGICKISTE: TM1638 MODELL 1 SCHALTUHR-MANAGER
// =======================================================================

Blockly.defineBlocksWithJsonArray([
    // 1. MENÜ-STEUERUNG (Blockiert Tasten 1-3 nur, wenn er aufgerufen wird)
    {
        "type": "ard_timer_tm1638_ctrl",
        "message0": "⏰ Zeige Schaltuhr (TM1638) Menü",
        "previousStatement": null,
        "nextStatement": null,
        "colour": 120,
        "tooltip": "Verwaltet die 7 Schaltuhr-Slots über das TM1638. Packe diesen Block in ein 'Wenn', um das Menü ein-/auszuschalten."
    },
    // 2. AUSWERTUNG & ZEITQUELLE
    {
        "type": "ard_timer_tm1638_eval",
        "message0": "⏰ Ist Schaltuhr (TM1638) aktiv? | Quelle: %1",
        "args0": [
            {
                "type": "field_dropdown",
                "name": "TIME_SRC",
                "options": [
                    ["Interne R4 RTC (oder NTP)", "INT"],
                    ["Externe RTC (I2C Modul)", "EXT"]
                ]
            }
        ],
        "output": "Boolean",
        "colour": 120,
        "tooltip": "Prüft die 7 Slots. Wähle aus, woher die Schaltuhr die aktuelle Uhrzeit nehmen soll."
    }
]);

// --- GEMEINSAMER C++ HEADER (TM1638) ---
function addTmTimerGlobals() {
    ArduinoGenerator.globals_.add(`
#ifndef TM_TIMER_GLOBALS
#define TM_TIMER_GLOBALS

struct TmTimerSlot {
  uint8_t mode; // 0=Inaktiv, 1=Dauer, 2=Impuls
  uint8_t days; // 0=Alle, 1=Mo-Fr, 2=Sa-So, 3=Mo, 4=Di, 5=Mi, 6=Do, 7=Fr, 8=Sa, 9=So
  uint8_t onH, onM, offH, offM;
};

TmTimerSlot tm_timers[7] = {
  {1, 0, 6, 0, 22, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}
};

int tm_curSlot = 0;   
int tm_curField = 0;  
unsigned long tm_lastBtn = 0;
unsigned long tm_slotImpulseTime[7] = {0};
bool tm_timerActive = false;

// Zentrale Logik-Auswertung (Uhr-unabhängig)
bool tm_evalTimerLogic(int curH, int curM, int curS, int curD) {
  int curMinTotal = (curH * 60) + curM;
  bool anyActive = false;

  for (int i = 0; i < 7; i++) {
    TmTimerSlot &s = tm_timers[i];
    if (s.mode == 0) continue; 

    bool dayOk = false;
    if (s.days == 0) dayOk = true; 
    else if (s.days == 1 && curD >= 1 && curD <= 5) dayOk = true; 
    else if (s.days == 2 && (curD == 6 || curD == 7)) dayOk = true; 
    else if (s.days >= 3 && (s.days - 2) == curD) dayOk = true; 

    if (!dayOk) continue;

    if (s.mode == 2) { // Impuls
      if (curH == s.onH && curM == s.onM && curS == 0) {
        if (millis() - tm_slotImpulseTime[i] > 2000) tm_slotImpulseTime[i] = millis();
      }
      if (millis() - tm_slotImpulseTime[i] <= 1000) anyActive = true;
    } else if (s.mode == 1) { // Dauer
      int onMin = (s.onH * 60) + s.onM;
      int offMin = (s.offH * 60) + s.offM;
      if (onMin <= offMin) {
        if (curMinTotal >= onMin && curMinTotal < offMin) anyActive = true;
      } else {
        if (curMinTotal >= onMin || curMinTotal < offMin) anyActive = true;
      }
    }
  }
  tm_timerActive = anyActive;
  return anyActive;
}

void tm_updateMenu() {
  uint8_t btns = tm.readButtons();
  if (btns != 0 && (millis() - tm_lastBtn > 200)) {
    tm_lastBtn = millis();
    if (btns & 1) { tm_curField = (tm_curField + 1) % 7; } 
    else if ((btns & 2) || (btns & 4)) {
      int dir = (btns & 2) ? 1 : -1;
      TmTimerSlot &s = tm_timers[tm_curSlot];
      switch(tm_curField) {
        case 0: tm_curSlot = (tm_curSlot + dir + 7) % 7; break;
        case 1: s.mode = (s.mode + dir + 3) % 3; break;
        case 2: s.days = (s.days + dir + 10) % 10; break;
        case 3: s.onH = (s.onH + dir + 24) % 24; break;
        case 4: s.onM = (s.onM + dir + 60) % 60; break;
        case 5: s.offH = (s.offH + dir + 24) % 24; break;
        case 6: s.offM = (s.offM + dir + 60) % 60; break;
      }
    }
  }

  bool blink = (millis() % 600) > 300;
  char buf[9]; 
  TmTimerSlot &s = tm_timers[tm_curSlot];

  if (tm_curField < 3) {
    sprintf(buf, "%d  %d  %d ", tm_curSlot + 1, s.mode, s.days);
    if (blink) {
      if (tm_curField == 0) buf[0] = ' ';
      if (tm_curField == 1) buf[3] = ' ';
      if (tm_curField == 2) buf[6] = ' ';
    }
  } else if (tm_curField == 3 || tm_curField == 4) {
    sprintf(buf, "%don%02d%02d ", tm_curSlot + 1, s.onH, s.onM);
    if (blink) {
      if (tm_curField == 3) { buf[3] = ' '; buf[4] = ' '; }
      if (tm_curField == 4) { buf[5] = ' '; buf[6] = ' '; }
    }
  } else {
    sprintf(buf, "%doF%02d%02d ", tm_curSlot + 1, s.offH, s.offM);
    if (blink) {
      if (tm_curField == 5) { buf[3] = ' '; buf[4] = ' '; }
      if (tm_curField == 6) { buf[5] = ' '; buf[6] = ' '; }
    }
  }
  tm.setDisplayToString(buf);
  for(int i = 0; i < 8; i++) tm.setLED(i, 0);
  tm.setLED(tm_curSlot, 1);
  if (tm_timerActive) tm.setLED(7, 1);
}
#endif
`);
}

// --- GENERATOREN ---
ArduinoGenerator.hardwareScanners['ard_timer_tm1638_ctrl'] = function(block) {
    addTmTimerGlobals();
};

ArduinoGenerator.forBlock['ard_timer_tm1638_ctrl'] = function(block) {
    // Wird jetzt direkt dort ausgeführt, wo der Block platziert wird! Keine Blockade mehr!
    return `  tm_updateMenu();\n`; 
};

ArduinoGenerator.hardwareScanners['ard_timer_tm1638_eval'] = function(block) {
    addTmTimerGlobals();
    const timeSrc = block.getFieldValue('TIME_SRC');
    
    if (timeSrc === 'INT') {
        ArduinoGenerator.includes_.add('#include "RTC.h"');
        ArduinoGenerator.globals_.add(`
bool tm_evalTimer_Int() {
  RTCTime t; RTC.getTime(t);
  return tm_evalTimerLogic(t.getHour(), t.getMinutes(), t.getSeconds(), (int)t.getDayOfWeek());
}
`);
    } else {
        ArduinoGenerator.globals_.add(`
bool tm_evalTimer_Ext() {
  DateTime now = extRTC.now();
  int dow = now.dayOfTheWeek();
  return tm_evalTimerLogic(now.hour(), now.minute(), now.second(), (dow == 0 ? 7 : dow));
}
`);
    }
};

ArduinoGenerator.forBlock['ard_timer_tm1638_eval'] = function(block) {
    const timeSrc = block.getFieldValue('TIME_SRC');
    return [(timeSrc === 'INT') ? 'tm_evalTimer_Int()' : 'tm_evalTimer_Ext()', 0];
};