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

LogiLadder.Nodes = {
    // --- I/O BAUSTEINE ---
    'input': {
        inputs: 0, outputs: 1, outType: 'bool',
        data: { varname: '', simval: false }, 
        html: `
            <div class="fup-title">Eingang</div>
            <div class="fup-body">
                Symbol <select df-varname class="fup-select-field var-dropdown" data-vartype="din"></select>
                <div class="sim-ui">Simulieren: <input type="checkbox" df-simval></div>
            </div>
        `,
        code: (id, data, ins) => `val_${id} = (digitalRead(PIN_${data.varname || 'ERR'}) == LOW);`,
        sim: (id, data, ins, state, millis) => {
            const el = document.getElementById('node-'+id);
            const cb = el ? el.querySelector('input[df-simval]') : null;
            return cb ? cb.checked : false;
        }
    },
    'output': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { varname: '' }, 
        html: `
            <div class="fup-title">Ausgang</div>
            <div class="fup-body">Symbol <select df-varname class="fup-select-field var-dropdown" data-vartype="dout"></select></div>
        `,
        code: (id, data, ins) => `digitalWrite(PIN_${data.varname || 'ERR'}, ${ins[0]} ? HIGH : LOW);`,
        sim: (id, data, ins, state, millis) => !!ins[0]
    },
    'analog_in': {
        inputs: 0, outputs: 1, outType: 'float',
        data: { varname: '', simval: 0 },
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">Analog IN</div>
            <div class="fup-body">
                Symbol <select df-varname class="fup-select-field var-dropdown" data-vartype="ain"></select>
                <div class="sim-ui">Sim-Wert: <input type="number" df-simval class="fup-input-field" value="0"></div>
            </div>
        `,
        code: (id, data, ins) => `val_${id} = analogRead(PIN_${data.varname || 'ERR'});`,
        sim: (id, data, ins, state, millis) => {
            const el = document.getElementById('node-'+id);
            const num = el ? el.querySelector('input[df-simval]') : null;
            return num ? parseFloat(num.value || 0) : 0;
        }
    },
    'analog_out': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { varname: '' },
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">PWM OUT</div>
            <div class="fup-body">Symbol <select df-varname class="fup-select-field var-dropdown" data-vartype="pwm"></select></div>
        `,
        code: (id, data, ins) => `analogWrite(PIN_${data.varname || 'ERR'}, (int)${ins[0]});`,
        sim: (id, data, ins, state, millis) => !!ins[0]
    },

    // --- INTERNE VARIABLEN ---
    'const_val': {
        inputs: 0, outputs: 1, outType: 'float',
        data: { value: 200 },
        html: `
            <div class="fup-title" style="background-color: #6610f2;">Festwert</div>
            <div class="fup-body">Wert <input type="number" df-value class="fup-input-field" value="200"></div>
        `,
        code: (id, data, ins) => `val_${id} = ${data.value || 0};`,
        sim: (id, data, ins, state, millis) => {
            const el = document.getElementById('node-'+id);
            const num = el ? el.querySelector('input[df-value]') : null;
            return num ? parseFloat(num.value || 0) : 0;
        }
    },
    'var_read': {
        inputs: 0, outputs: 1, outType: 'float', 
        data: { name: '' },
        html: `
            <div class="fup-title" style="background-color: #6610f2;">Var Lesen</div>
            <div class="fup-body">Symbol <select df-name class="fup-select-field var-dropdown" data-vartype="internal"></select></div>
        `,
        code: (id, data, ins) => `val_${id} = ${data.name || '0'};`,
        sim: (id, data, ins, state, millis) => LogiLadder.Simulator.mem[data.name] || 0
    },
    'var_write': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { name: '' },
        html: `
            <div class="fup-title" style="background-color: #6610f2;">Var Schreiben</div>
            <div class="fup-body">Symbol <select df-name class="fup-select-field var-dropdown" data-vartype="internal"></select></div>
        `,
        code: (id, data, ins) => `${data.name || 'VarError'} = ${ins[0]};`,
        sim: (id, data, ins, state, millis) => { LogiLadder.Simulator.mem[data.name] = ins[0]; return !!ins[0]; }
    },

    // --- DIGITALE LOGIK ---
    'and': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">&amp;</div><div class="fup-body">UND</div>`,
        code: (id, data, ins) => `val_${id} = (${ins[0]} && ${ins[1]});`,
        sim: (id, data, ins, state, millis) => !!(ins[0] && ins[1])
    },
    'or': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">≥1</div><div class="fup-body">ODER</div>`,
        code: (id, data, ins) => `val_${id} = (${ins[0]} || ${ins[1]});`,
        sim: (id, data, ins, state, millis) => !!(ins[0] || ins[1])
    },
    'not': {
        inputs: 1, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">NOT</div><div class="fup-body">NICHT</div>`,
        code: (id, data, ins) => `val_${id} = !${ins[0]};`,
        sim: (id, data, ins, state, millis) => !ins[0]
    },
    'xor': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">XOR</div><div class="fup-body">EXKLUSIV ODER</div>`,
        code: (id, data, ins) => `val_${id} = (${ins[0]} != ${ins[1]});`,
        sim: (id, data, ins, state, millis) => Boolean(ins[0]) !== Boolean(ins[1])
    },
    'merker': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { name: 'M1' },
        html: `
            <div class="fup-title">Merker</div>
            <div class="fup-body">Name <input type="text" df-name class="fup-input-field" value="M1" style="width:50px;"></div>
        `,
        globals: (id, data) => `bool merker_${id} = false; // ${data.name || 'M1'}`,
        code: (id, data, ins) => `merker_${id} = ${ins[0]};`,
        sim: (id, data, ins, state, millis) => !!ins[0]
    },

    // --- FLANKEN ---
    'rtrig': {
        inputs: 1, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">R_TRIG</div><div class="fup-body">Flanke Pos.</div>`,
        globals: (id) => `LogiRTRIG rtrig_${id};`,
        code: (id, data, ins) => `val_${id} = rtrig_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => { let q = (ins[0] && !state.lastIn); state.lastIn = ins[0]; return q; }
    },
    'ftrig': {
        inputs: 1, outputs: 1, outType: 'bool',
        html: `<div class="fup-title">F_TRIG</div><div class="fup-body">Flanke Neg.</div>`,
        globals: (id) => `LogiFTRIG ftrig_${id};`,
        code: (id, data, ins) => `val_${id} = ftrig_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => { let q = (!ins[0] && state.lastIn); state.lastIn = ins[0]; return q; }
    },

    // --- SPEICHER & RELAIS ---
    'rs': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `
            <div class="fup-title">RS</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">S<br><br><br>R1</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
            </div>
        `,
        globals: (id) => `LogiRS rs_${id};`,
        code: (id, data, ins) => `val_${id} = rs_${id}.update(${ins[0]}, ${ins[1]});`,
        sim: (id, data, ins, state, millis) => { if (ins[1]) state.q = false; else if (ins[0]) state.q = true; return !!state.q; }
    },
    'sr': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `
            <div class="fup-title">SR</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">S1<br><br><br>R</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
            </div>
        `,
        globals: (id) => `LogiSR sr_${id};`,
        code: (id, data, ins) => `val_${id} = sr_${id}.update(${ins[0]}, ${ins[1]});`,
        sim: (id, data, ins, state, millis) => { if (ins[0]) state.q = true; else if (ins[1]) state.q = false; return !!state.q; }
    },
    'tff': {
        inputs: 2, outputs: 1, outType: 'bool',
        html: `
            <div class="fup-title">T_FF</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">TOG<br><br><br>RES</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Stromstoß
            </div>
        `,
        globals: (id) => `LogiTFF tff_${id};`,
        code: (id, data, ins) => `val_${id} = tff_${id}.update(${ins[0]}, ${ins[1]});`,
        sim: (id, data, ins, state, millis) => {
            if (ins[1]) state.q = false;
            else if (ins[0] && !state.lastIn) state.q = !state.q;
            state.lastIn = ins[0];
            return !!state.q;
        }
    },

    // --- ZEIT & ZÄHLER ---
    'ton': {
        inputs: 2, outputs: 1, outType: 'bool',
        data: { time: 1000 },
        html: `
            <div class="fup-title">TON</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">IN<br><br><br>PT</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Zeit (ms) <input type="number" df-time class="fup-input-field" value="1000">
            </div>
        `,
        globals: (id, data) => `LogiTON ton_${id}(${data.time || 1000});`,
        code: (id, data, ins) => `val_${id} = ton_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => {
            let pt = parseFloat(data.time || 1000);
            if (ins[0]) {
                if (!state.startTime) state.startTime = millis;
                if (millis - state.startTime >= pt) state.q = true;
            } else { state.startTime = 0; state.q = false; }
            return !!state.q;
        }
    },
    'tof': {
        inputs: 2, outputs: 1, outType: 'bool',
        data: { time: 1000 },
        html: `
            <div class="fup-title">TOF</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">IN<br><br><br>PT</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Zeit (ms) <input type="number" df-time class="fup-input-field" value="1000">
            </div>
        `,
        globals: (id, data) => `LogiTOF tof_${id}(${data.time || 1000});`,
        code: (id, data, ins) => `val_${id} = tof_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => {
            let pt = parseFloat(data.time || 1000);
            if (ins[0]) { state.startTime = 0; state.q = true; }
            else if (state.q) {
                if (!state.startTime) state.startTime = millis;
                if (millis - state.startTime >= pt) state.q = false;
            }
            return !!state.q;
        }
    },
    'tp': {
        inputs: 2, outputs: 1, outType: 'bool',
        data: { time: 500 },
        html: `
            <div class="fup-title">TP</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">IN<br><br><br>PT</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Impuls (ms) <input type="number" df-time class="fup-input-field" value="500">
            </div>
        `,
        globals: (id, data) => `LogiTP tp_${id}(${data.time || 500});`,
        code: (id, data, ins) => `val_${id} = tp_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => {
            let pt = parseFloat(data.time || 500);
            if (ins[0] && !state.q && !state.startTime) { state.startTime = millis; state.q = true; }
            if (state.q) { if (millis - state.startTime >= pt) state.q = false; } 
            else if (!ins[0]) { state.startTime = 0; }
            return !!state.q;
        }
    },
    'tonr': {
        inputs: 2, outputs: 1, outType: 'bool',
        data: { time: 5000 },
        html: `
            <div class="fup-title">TONR</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">IN<br><br><br>RES</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Speicherzeit <input type="number" df-time class="fup-input-field" value="5000">
            </div>
        `,
        globals: (id, data) => `LogiTONR tonr_${id}(${data.time || 5000});`,
        code: (id, data, ins) => `val_${id} = tonr_${id}.update(${ins[0]}, ${ins[1]});`,
        sim: (id, data, ins, state, millis) => {
            let pt = parseFloat(data.time || 5000);
            if (ins[1]) { state.accum = 0; state.q = false; state.timing = false; }
            else {
                if (ins[0]) {
                    if (!state.timing) { state.lastTime = millis; state.timing = true; }
                    state.accum = (state.accum || 0) + (millis - state.lastTime);
                    state.lastTime = millis;
                    if (state.accum >= pt) state.q = true;
                } else { state.timing = false; }
            }
            return !!state.q;
        }
    },
    'counter': {
        inputs: 3, outputs: 1, outType: 'bool',
        data: { limit: 10 },
        html: `
            <div class="fup-title">Zähler</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">CU<br>CD<br>RES</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
                Grenzwert:
                <input type="number" df-limit class="fup-input-field" value="10">
            </div>
        `,
        globals: (id, data) => `LogiCTUD counter_${id}(${data.limit || 10});`,
        code: (id, data, ins) => `val_${id} = counter_${id}.update(${ins[0]}, ${ins[1]}, ${ins[2]});`,
        sim: (id, data, ins, state, millis) => {
            let limit = parseInt(data.limit || 10);
            if (ins[2]) state.cv = 0;
            else {
                if (ins[0] && !state.lastCU) state.cv = (state.cv || 0) + 1;
                if (ins[1] && !state.lastCD) state.cv = (state.cv || 0) - 1;
            }
            state.lastCU = ins[0]; state.lastCD = ins[1];
            return (state.cv >= limit);
        }
    },

    // --- ANALOG & MATHE ---
    'compare': {
        inputs: 2, outputs: 1, outType: 'bool',
        data: { op: '>' },
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">Vergleich</div>
            <div class="fup-body">
                <select df-op class="fup-select-field">
                    <option value=">">A &gt; B</option>
                    <option value="<">A &lt; B</option>
                    <option value=">=">A &ge; B</option>
                    <option value="<=">A &le; B</option>
                    <option value="==">A == B</option>
                    <option value="!=">A &ne; B</option>
                </select>
            </div>
        `,
        code: (id, data, ins) => `val_${id} = (${ins[0]} ${data.op || '>'} ${ins[1]});`,
        sim: (id, data, ins, state, millis) => {
            let op = data.op || '>', a = parseFloat(ins[0]||0), b = parseFloat(ins[1]||0);
            if(op==='>') return a > b; if(op==='<') return a < b; if(op==='>=') return a >= b;
            if(op==='<=') return a <= b; if(op==='==') return a === b; if(op==='!=') return a !== b; return false;
        }
    },
    'math': {
        inputs: 2, outputs: 1, outType: 'float',
        data: { op: '+' },
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">Mathe</div>
            <div class="fup-body">
                <select df-op class="fup-select-field">
                    <option value="+">A + B</option>
                    <option value="-">A - B</option>
                    <option value="*">A &times; B</option>
                    <option value="/">A &divide; B</option>
                </select>
            </div>
        `,
        code: (id, data, ins) => `val_${id} = (${ins[0]} ${data.op || '+'} ${ins[1]});`,
        sim: (id, data, ins, state, millis) => {
            let op = data.op || '+', a = parseFloat(ins[0]||0), b = parseFloat(ins[1]||0);
            if(op==='+') return a + b; if(op==='-') return a - b; if(op==='*') return a * b;
            if(op==='/') return b !== 0 ? a / b : 0; return 0;
        }
    },
    'map': {
        inputs: 1, outputs: 1, outType: 'float',
        data: { inmin: 0, inmax: 1023, outmin: 0, outmax: 100 },
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">Skalieren</div>
            <div class="fup-body" style="font-size: 10px;">
                IN Min: <input type="number" df-inmin class="fup-input-field" value="0">
                IN Max: <input type="number" df-inmax class="fup-input-field" value="1023">
                OUT Min: <input type="number" df-outmin class="fup-input-field" value="0">
                OUT Max: <input type="number" df-outmax class="fup-input-field" value="100">
            </div>
        `,
        code: (id, data, ins) => `val_${id} = map(${ins[0]}, ${data.inmin||0}, ${data.inmax||1023}, ${data.outmin||0}, ${data.outmax||100});`,
        sim: (id, data, ins, state, millis) => {
            let val = parseFloat(ins[0]||0), iMin = parseFloat(data.inmin||0), iMax = parseFloat(data.inmax||1023);
            let oMin = parseFloat(data.outmin||0), oMax = parseFloat(data.outmax||100);
            return (val - iMin) * (oMax - oMin) / (iMax - iMin) + oMin;
        }
    },
    'analog_mux': {
        inputs: 3, outputs: 1, outType: 'float',
        html: `
            <div class="fup-title" style="background-color: #fd7e14;">Schalter</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">S<br>IN 1<br>IN 2</div>
                    <div style="text-align:right;"><br>Q</div>
                </div>
            </div>
        `,
        code: (id, data, ins) => `val_${id} = (${ins[0]}) ? (${ins[1]}) : (${ins[2]});`,
        sim: (id, data, ins, state, millis) => ins[0] ? parseFloat(ins[1]||0) : parseFloat(ins[2]||0)
    },

    // --- ANZEIGE ---
    'lcd_msg': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { prio: 1, line1: '', line2: '' },
        html: `
            <div class="fup-title" style="background-color: #17a2b8;">LCD Meldetext</div>
            <div class="fup-body">
                <div style="font-size: 10px; color: #6c757d; text-align: left; margin-bottom: 5px;">EN (Aktivierung)</div>
                <div style="display: flex; align-items: center; justify-content: space-between; font-size: 10px;">
                    Prio: <input type="number" df-prio class="fup-input-field" value="1" style="width: 50px; margin-top:0;">
                </div>
                <input type="text" df-line1 class="fup-input-field" placeholder="Zeile 1" value="" maxlength="16">
                <input type="text" df-line2 class="fup-input-field" placeholder="Zeile 2" value="" maxlength="16">
            </div>
        `,
        globals: (id, data) => `LogiMsg msg_${id}(${data.prio || 1}, "${data.line1 || ''}", "${data.line2 || ''}");`,
        code: (id, data, ins) => `msg_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => !!ins[0]
    },
    'serial_print': {
        inputs: 1, outputs: 0, outType: 'bool',
        data: { text: 'Wert:' },
        html: `
            <div class="fup-title" style="background-color: #17a2b8;">Serial Print</div>
            <div class="fup-body">
                <input type="text" df-text class="fup-input-field" value="Wert:">
                <div style="font-size: 10px; color: #6c757d; text-align: left; margin-top: 5px;">IN (Druckt bei Änderung)</div>
            </div>
        `,
        globals: (id, data) => `float last_serial_${id} = -9999.0;`,
        code: (id, data, ins) => `
  if(abs(${ins[0]} - last_serial_${id}) > 0.01) { 
    Serial.print("${data.text} "); 
    Serial.println(${ins[0]}); 
    last_serial_${id} = ${ins[0]}; 
  }`,
        sim: (id, data, ins, state, millis) => {
            if (Math.abs((parseFloat(ins[0])||0) - (state.lastOut||-9999.0)) > 0.01) {
                console.log(`[SIM Serial] ${data.text} ${parseFloat(ins[0])||0}`);
                state.lastOut = parseFloat(ins[0])||0;
            }
            return !!ins[0];
        }
    },
	
	// --- KLIMA & REGELUNG ---
    'twopoint': {
        inputs: 3, outputs: 1, outType: 'bool',
        data: { mode: '0' },
        html: `
            <div class="fup-title" style="background-color: #0d6efd;">2-Punkt-Regler</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">Soll<br>Ist<br>Hyst.</div>
                    <div style="text-align:right;"><br><br>Q</div>
                </div>
                <select df-mode class="fup-select-field">
                    <option value="0">Heizen</option>
                    <option value="1">Kühlen</option>
                </select>
            </div>
        `,
        globals: (id, data) => `Logi2Point twopoint_${id}(${data.mode === '1' ? 'true' : 'false'});`,
        code: (id, data, ins) => `val_${id} = twopoint_${id}.update(${ins[0]}, ${ins[1]}, ${ins[2]});`,
        sim: (id, data, ins, state, millis) => {
            let sp = parseFloat(ins[0]||0), pv = parseFloat(ins[1]||0), hyst = parseFloat(ins[2]||0);
            let halfHyst = hyst / 2.0;
            if (data.mode === '1') { 
                if (pv > sp + halfHyst) state.q = true; else if (pv < sp - halfHyst) state.q = false;
            } else { 
                if (pv < sp - halfHyst) state.q = true; else if (pv > sp + halfHyst) state.q = false;
            }
            return !!state.q;
        }
    },
    'pid': {
        inputs: 2, outputs: 1, outType: 'float',
        data: { kp: 1.0, ki: 0.1, kd: 0.05 },
        html: `
            <div class="fup-title" style="background-color: #0d6efd;">PID-Regler</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">Soll<br>Ist</div>
                    <div style="text-align:right;"><br>Y</div>
                </div>
                <div style="text-align:left; font-size:10px;">
                    P: <input type="number" df-kp class="fup-input-field" value="1.0" step="0.1" style="width: 40px; padding: 2px;">
                    I: <input type="number" df-ki class="fup-input-field" value="0.1" step="0.01" style="width: 40px; padding: 2px;">
                    D: <input type="number" df-kd class="fup-input-field" value="0.05" step="0.01" style="width: 40px; padding: 2px;">
                </div>
            </div>
        `,
        globals: (id, data) => `LogiPID pid_${id}(${data.kp||1.0}, ${data.ki||0.1}, ${data.kd||0.05});`,
        code: (id, data, ins) => `val_${id} = pid_${id}.update(${ins[0]}, ${ins[1]});`,
        sim: (id, data, ins, state, millis) => {
            return 0.0; // PID ist in JavaScript ohne simulierbare Anlagen-Physik nicht sinnvoll darstellbar
        }
    },
    'pt1': {
        inputs: 1, outputs: 1, outType: 'float',
        data: { t1: 2.0 },
        html: `
            <div class="fup-title" style="background-color: #0d6efd;">PT1-Filter</div>
            <div class="fup-body">
                <div style="display:flex; justify-content: space-between; font-size: 10px; color: #6c757d; font-weight:bold;">
                    <div style="text-align:left;">Ist</div>
                    <div style="text-align:right;">Y</div>
                </div>
                Zeit (s): <input type="number" df-t1 class="fup-input-field" value="2.0" step="0.1">
            </div>
        `,
        globals: (id, data) => `LogiPT1 pt1_${id}(${data.t1||2.0});`,
        code: (id, data, ins) => `val_${id} = pt1_${id}.update(${ins[0]});`,
        sim: (id, data, ins, state, millis) => {
            let pv = parseFloat(ins[0]||0);
            if (!state.init) { state.y = pv; state.lastT = millis; state.init = true; return pv; }
            let dt = (millis - state.lastT) / 1000.0;
            state.lastT = millis;
            let t1 = parseFloat(data.t1||2.0);
            if (t1 <= 0) return pv;
            let alpha = dt / (t1 + dt);
            state.y = state.y + alpha * (pv - state.y);
            return state.y;
        }
    },

    // --- AUTOMATION ---
    'weekly_timer': {
        inputs: 3, outputs: 1, outType: 'bool',
        data: { sh: 8, sm: 0, eh: 17, em: 0, d1: true, d2: true, d3: true, d4: true, d5: true, d6: false, d7: false },
        html: `
            <div class="fup-title" style="background-color: #ffc107; color: black;">Schaltuhr</div>
            <div class="fup-body" style="font-size: 10px; text-align: left;">
                <div style="display:flex; justify-content: space-between; color: #6c757d; font-weight:bold; margin-bottom: 5px;">
                    <div style="text-align:left;">Tag (1=Mo)<br>Std (0-23)<br>Min (0-59)</div>
                    <div style="text-align:right;"><br><br>Q</div>
                </div>
                Von: <input type="number" df-sh style="width: 32px;" value="8">:<input type="number" df-sm style="width: 32px;" value="0"><br>
                Bis: <input type="number" df-eh style="width: 32px;" value="17">:<input type="number" df-em style="width: 32px;" value="0">
                <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 2px; margin-top: 5px;">
                    <label>Mo<input type="checkbox" df-d1 checked></label>
                    <label>Di<input type="checkbox" df-d2 checked></label>
                    <label>Mi<input type="checkbox" df-d3 checked></label>
                    <label>Do<input type="checkbox" df-d4 checked></label>
                    <label>Fr<input type="checkbox" df-d5 checked></label>
                    <label>Sa<input type="checkbox" df-d6></label>
                    <label>So<input type="checkbox" df-d7></label>
                </div>
            </div>
        `,
        globals: (id, data) => `LogiWeeklyTimer wtimer_${id}(${data.sh||0}, ${data.sm||0}, ${data.eh||0}, ${data.em||0}, ${data.d1?'true':'false'}, ${data.d2?'true':'false'}, ${data.d3?'true':'false'}, ${data.d4?'true':'false'}, ${data.d5?'true':'false'}, ${data.d6?'true':'false'}, ${data.d7?'true':'false'});`,
        code: (id, data, ins) => `val_${id} = wtimer_${id}.update((int)${ins[0]}, (int)${ins[1]}, (int)${ins[2]});`,
        sim: (id, data, ins, state, millis) => {
            let day = parseInt(ins[0]||0), h = parseInt(ins[1]||0), m = parseInt(ins[2]||0);
            if(day < 1 || day > 7) return false;
            let active = [false, data.d1, data.d2, data.d3, data.d4, data.d5, data.d6, data.d7];
            if(!active[day]) return false;
            let cur = h*60 + m; 
            let start = parseInt(data.sh||0)*60 + parseInt(data.sm||0); 
            let end = parseInt(data.eh||0)*60 + parseInt(data.em||0);
            if(start <= end) return (cur >= start && cur < end);
            return (cur >= start || cur < end);
        }
    }
	
	
	
	
	
};