/**
 * logic_edges.js
 * Flankenerkennung (Rising/Falling Edge)
 * Kompatibel mit dem custom ArduinoGenerator
 */

// =======================================================================
// 1. BLOCK-DEFINITIONEN (UI & VERHALTEN)
// =======================================================================

// Variante A: Als Wahrheitswert (Spitzer Block für WENN-Bedingungen)
Blockly.Blocks['ard_edge_value'] = {
    init: function() {
        this.setColour(230); // Farbe passend zur Kategorie "Logik"
        this.appendValueInput('SIGNAL')
            .setCheck(['Boolean', 'Number'])
            .appendField('Bei')
            .appendField(new Blockly.FieldDropdown([
                ['steigender Flanke (0 ➔ 1)', 'RISING'],
                ['fallender Flanke (1 ➔ 0)', 'FALLING']
            ]), 'EDGE_TYPE')
            .appendField('von');
        this.setOutput(true, 'Boolean');
        this.setTooltip('Gibt für genau einen Durchlauf WAHR zurück, wenn das Signal wechselt.');
    }
};

// Variante B: Als Aktions-Block (Klammer-Block für Aktionen)
Blockly.Blocks['ard_edge_statement'] = {
    init: function() {
        this.setColour(230); // Farbe passend zur Kategorie "Logik"
        this.setPreviousStatement(true, null);
        this.setNextStatement(true, null);
        this.appendValueInput('SIGNAL')
            .setCheck(['Boolean', 'Number'])
            .appendField('Bei')
            .appendField(new Blockly.FieldDropdown([
                ['steigender Flanke (0 ➔ 1)', 'RISING'],
                ['fallender Flanke (1 ➔ 0)', 'FALLING']
            ]), 'EDGE_TYPE')
            .appendField('von');
        this.appendStatementInput('DO')
            .appendField('mache:');
        this.setTooltip('Führt die enthaltene Aktion genau einmal aus, wenn das Signal wechselt.');
    }
};


// =======================================================================
// 2. GENERATOR-LOGIK (C++ CODE ERZEUGUNG)
// =======================================================================

// Generator für Variante A (Wert-Block)
ArduinoGenerator.forBlock['ard_edge_value'] = function(block) {
    const edgeType = block.getFieldValue('EDGE_TYPE');
    // Die 0 steht für ArduinoGenerator.PRECEDENCE
    const signalCode = ArduinoGenerator.valueToCode(block, 'SIGNAL', 0) || 'false';
    
    // Wir nutzen eine C++11 Lambda-Funktion, die sofort ausgeführt wird.
    // So kann der Block inline in ein if() gesteckt werden und verwaltet
    // trotzdem seine eigene lokale static-Variable. 
    // [&] stellt sicher, dass alle globalen/lokalen Variablen erreichbar bleiben.
    
    let condition = edgeType === 'RISING' 
        ? '(currState && !lastState)' 
        : '(!currState && lastState)';

    const code = `([&]() -> bool { static bool lastState = false; bool currState = ${signalCode}; bool triggered = ${condition}; lastState = currState; return triggered; })()`;
    
    return [code, 0]; // Gibt den Code und die Precedence zurück
};

// Generator für Variante B (Aktions-Block)
ArduinoGenerator.forBlock['ard_edge_statement'] = function(block) {
    const edgeType = block.getFieldValue('EDGE_TYPE');
    const signalCode = ArduinoGenerator.valueToCode(block, 'SIGNAL', 0) || 'false';
    const branchCode = ArduinoGenerator.statementToCode(block, 'DO');
    
    // Eindeutige ID generieren (verhindert Konflikte, wenn der Block mehrfach kopiert wird)
    const safeId = block.id.replace(/[^a-zA-Z0-9]/g, '_');
    
    let condition = edgeType === 'RISING' 
        ? `(currState_${safeId} && !lastState_${safeId})` 
        : `(!currState_${safeId} && lastState_${safeId})`;

    let code = '';
    code += `  static bool lastState_${safeId} = false;\n`;
    code += `  bool currState_${safeId} = ${signalCode};\n`;
    code += `  if (${condition}) {\n`;
    code += branchCode;
    code += `  }\n`;
    code += `  lastState_${safeId} = currState_${safeId};\n`;
    
    return code;
};