// =======================================================================
// LOGIKKISTE - STATE ENGINE (4-ZONEN FUNKTIONSZEIGER)
// =======================================================================

Blockly.defineBlocksWithJsonArray([
    // --- 1. STATE ENGINE MAIN (4-ZONEN CONTAINER) ---
    {
        "type": "ard_state_engine_main",
        "message0": "State Engine (Ablaufsteuerung) ⚙️",
        "message1": "Zykluszeit (ms): %1 | Start-Zustand (ID): %2",
        "args1": [
            {"type": "field_number", "name": "CYCLE_TIME", "value": 10, "min": 0, "max": 10000},
            {"type": "field_number", "name": "START_STATE", "value": 1}
        ],
        "message2": "Zone 0: Echtzeit-Schutz %1",
        "args2": [{"type": "input_statement", "name": "ZONE0"}],
        "message3": "Zone 1: Eingänge (Read) %1",
        "args3": [{"type": "input_statement", "name": "ZONE1"}],
        "message4": "Zone 2: Zustände (Zeiger) %1",
        "args4": [{"type": "input_statement", "name": "ZONE2", "check": "StateEngineCase"}],
        "message5": "Zone 3: Ausgänge (Write) %1",
        "args5": [{"type": "input_statement", "name": "ZONE3"}],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 250,
        "tooltip": "Die professionelle State Engine. Trennt Echtzeit, Eingaben, Zustandslogik und Ausgaben. Nutzt performante Funktionszeiger."
    },

    // --- 2. EINZELNER ZUSTAND (MIT ODER-LOGIK) ---
    {
        "type": "ard_state_engine_state",
        "message0": "Zustands-IDs (z.B. 1, 5, 7): %1 %2 Mache:",
        "args0": [
            {"type": "field_input", "name": "STATES", "text": "1"},
            {"type": "input_dummy"}
        ],
        "message1": "%1",
        "args1": [{"type": "input_statement", "name": "DO"}],
        "previousStatement": "StateEngineCase", 
        "nextStatement": "StateEngineCase",     
        "colour": 250,
        "tooltip": "Definiert einen Zustand. Du kannst mehrere IDs mit Komma trennen (ODER-Logik). Darf nur in Zone 2 platziert werden!"
    },

    // --- 3. ZUSTAND WECHSELN ---
    {
        "type": "ard_state_engine_change",
        "message0": "Wechsle zu Zustand (ID): %1",
        "args0": [
            {"type": "input_value", "name": "NEXT_STATE", "check": "Number"}
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 250,
        "tooltip": "Ändert den Zustandszeiger und springt sofort aus dem aktuellen Zustand heraus in Zone 3."
    },

    // --- 4. ZUSTANDS-DAUER ABFRAGEN ---
    {
        "type": "ard_state_engine_time",
        "message0": "Dauer im aktuellen Zustand (ms)",
        "output": "Number",
        "colour": 250,
        "tooltip": "Gibt automatisch die Zeit in Millisekunden zurück, die seit dem letzten Zustandswechsel vergangen ist."
    }
]);


// =======================================================================
// C++ CODE GENERATOREN
// =======================================================================

// --- 1. GENERATOR: STATE ENGINE MAIN ---
ArduinoGenerator.forBlock['ard_state_engine_main'] = function(block) {
    const cycleTime = block.getFieldValue('CYCLE_TIME');
    const startState = block.getFieldValue('START_STATE');
    
    const zone0 = ArduinoGenerator.statementToCode(block, 'ZONE0');
    const zone1 = ArduinoGenerator.statementToCode(block, 'ZONE1');
    const zone3 = ArduinoGenerator.statementToCode(block, 'ZONE3');

    // Wir lesen Zone 2 manuell aus, um aus den Blöcken C++ Funktionen zu generieren
    let funcsCode = "";
    let switchCode = "";
    let stateBlock = block.getInputTargetBlock('ZONE2');
    
    while (stateBlock) {
        if (stateBlock.type === 'ard_state_engine_state') {
            const ids = stateBlock.getFieldValue('STATES').split(',');
            const funcName = 'se_func_' + stateBlock.id.replace(/[^a-zA-Z0-9]/g, '');
            
            // Code des Inhalts auslesen
            const doCode = ArduinoGenerator.statementToCode(stateBlock, 'DO');
            
            // C++ Funktion für den Zeiger erstellen
            funcsCode += `void ${funcName}() {\n${doCode}}\n\n`;
            
            // Switch-Case Zuweisungen für den Dispatcher bauen (ODER-Logik)
            ids.forEach(id => {
                const num = parseInt(id.trim());
                if (!isNaN(num)) {
                    switchCode += `    case ${num}: se_currentState = ${funcName}; break;\n`;
                }
            });
        }
        stateBlock = stateBlock.getNextBlock();
    }

    // Globale Variablen und Definitionen für die State Engine anlegen
    ArduinoGenerator.globals_.add(`typedef void (*StateFunc)();`);
    ArduinoGenerator.globals_.add(`StateFunc se_currentState = nullptr;`);
    ArduinoGenerator.globals_.add(`unsigned long se_stateTime = 0;`);
    ArduinoGenerator.globals_.add(`unsigned long se_lastCycle = 0;`);
    ArduinoGenerator.globals_.add(`const int se_cycleTime = ${cycleTime};`);
    
    // Die generierten Funktionen in den globalen Bereich schreiben
    ArduinoGenerator.globals_.add(funcsCode);
    
    // Die Umschalt-Funktion (Dispatcher) definieren
    ArduinoGenerator.globals_.add(`void se_changeState(int nextState) {
  se_stateTime = millis();
  switch (nextState) {
${switchCode}    default: se_currentState = nullptr; break;
  }
}`);

    // Auto-Setup: Startzustand beim Hochfahren setzen
    ArduinoGenerator.autoSetup_.push(`  se_changeState(${startState});\n`);

    // Den fertigen Loop-Code mit den 4 Zonen zusammenbauen
    let code = `  // --- Zone 0: Echtzeit-Schutz ---
${zone0}
  // --- Zykluszeit-Sperre ---
  if (se_cycleTime == 0 || (millis() - se_lastCycle >= se_cycleTime)) {
    if (se_cycleTime > 0) se_lastCycle = millis();

    // --- Zone 1: Eingänge (Read) ---
${zone1}
    // --- Zone 2: Zustände (Zeiger ausführen) ---
    if (se_currentState != nullptr) {
      se_currentState();
    }

    // --- Zone 3: Ausgänge (Write) ---
${zone3}  }\n`;

    return code;
};

// --- 2. GENERATOR: EINZELNER ZUSTAND ---
ArduinoGenerator.forBlock['ard_state_engine_state'] = function(block) {
    // Da wir die Funktionen bereits im Main-Block manuell auslesen und global platzieren,
    // darf dieser Block lokal im Loop keinen Text zurückgeben!
    return '';
};

// --- 3. GENERATOR: ZUSTAND WECHSELN ---
ArduinoGenerator.forBlock['ard_state_engine_change'] = function(block) {
    const nextState = ArduinoGenerator.valueToCode(block, 'NEXT_STATE', 0) || '0';
    // 'return' bricht die aktuelle Funktionszeiger-Ausführung ab und springt sauber in Zone 3
    return `  se_changeState(${nextState});\n  return;\n`;
};

// --- 4. GENERATOR: ZUSTANDS-DAUER ABFRAGEN ---
ArduinoGenerator.forBlock['ard_state_engine_time'] = function(block) {
    // Gibt einfach die Differenz zur gespeicherten Zeit zurück
    const code = `(millis() - se_stateTime)`;
    return [code, 0];
};