window.LogiLadder = window.LogiLadder || {};

LogiLadder.CodeGen = {
    generate: function(editorData) {
        if (!editorData || !editorData.drawflow.Home.data) return;
        const nodes = editorData.drawflow.Home.data;
        
        let finalCode = "#include <LogiLadder.h>\n";
        
        // Prüfen, ob ein LCD-Baustein im Projekt existiert
        let hasLCD = Object.values(nodes).some(n => n.name === 'lcd_msg');

        if (hasLCD) {
            finalCode += "#include <Wire.h>\n";
            finalCode += "#include <LiquidCrystal_I2C.h>\n\n";
            finalCode += "// --- Display Initialisierung ---\n";
            finalCode += "LiquidCrystal_I2C lcd(0x27, 16, 2);\n";
            finalCode += "LogiLCDManager lcdManager(&lcd);\n";
        }
        finalCode += "\n";

        let codeDefines = "// --- Hardware Mapping (Pins) ---\n";
        let codeVars = "// --- Symboltabelle (Interne Variablen) ---\n";
        
        let codeSetup = "void setup() {\n  Serial.begin(115200);\n";
        let codeLoop = "void loop() {\n  unsigned long currentMillis = millis();\n\n";
        
        if (hasLCD) {
            codeSetup += "  // Display Start\n  lcd.init();\n  lcd.backlight();\n";
        }
        
        // 1. Symboltabelle auswerten (I/O & Variablen)
        if (window.LogiLadder.Variables && window.LogiLadder.Variables.length > 0) {
            window.LogiLadder.Variables.forEach(v => {
                if (v.hw === 'shield1') {
                    codeSetup += `  // TODO: Shield Init für ${v.name} (I2C)\n`;
                } else if (v.hw === 'onboard') {
                    if (['din', 'dout', 'ain', 'pwm'].includes(v.type)) {
                        codeDefines += `#define PIN_${v.name} ${v.pinval}\n`;
                        if (v.type === 'din') codeSetup += `  pinMode(PIN_${v.name}, INPUT_PULLUP);\n`;
                        if (v.type === 'dout') codeSetup += `  pinMode(PIN_${v.name}, OUTPUT);\n`;
                    }
                } else if (v.hw === 'none' && ['int', 'float', 'bool'].includes(v.type)) {
                    codeVars += `${v.type} ${v.name} = ${v.pinval};\n`;
                }
            });
        }
        
        // 2. FUP-Netzwerk auswerten
        let nodeLogic = [];
        let codeGlobals = "\n// --- Baustein-Instanzen & Zyklus-Speicher ---\n";

        for (const [id, node] of Object.entries(nodes)) {
            const def = LogiLadder.Nodes[node.name];
            if (!def) continue;

            if (def.outputs > 0) {
                let outType = def.outType || 'bool';
                let initVal = (outType === 'bool') ? 'false' : '0.0';
                codeGlobals += `${outType} val_${id} = ${initVal}; // ${node.name}\n`;
            }

            if (def.globals) {
                codeGlobals += def.globals(id, node.data) + "\n";
            }

            // NEU: Dem LCD-Manager den Baustein übergeben
            if (node.name === 'lcd_msg') {
                codeSetup += `  lcdManager.addMsg(&msg_${id});\n`;
            }

            let resolvedInputs = [];
            for (let i = 1; i <= def.inputs; i++) {
                let conn = node.inputs[`input_${i}`].connections;
                if (conn.length > 0) {
                    resolvedInputs.push(`val_${conn[0].node}`);
                } else {
                    resolvedInputs.push(`false`);
                }
            }

            nodeLogic.push(`  // Baustein: ${node.name} (ID: ${id})`);
            nodeLogic.push(`  ${def.code(id, node.data, resolvedInputs)}\n`);
        }

        if (hasLCD) {
            nodeLogic.push(`  // --- Display Manager Update ---`);
            nodeLogic.push(`  lcdManager.update();\n`);
        }

        // --- C++ Code final zusammensetzen ---
        finalCode += codeDefines + "\n";
        finalCode += codeVars;
        finalCode += codeGlobals + "\n";
        
        codeSetup += "}\n\n";
        
        finalCode += codeSetup;
        finalCode += codeLoop;
        finalCode += nodeLogic.join("\n");
        finalCode += "}\n";

        document.getElementById('arduino-code-output').innerText = finalCode;
    }
};