Blockly.defineBlocksWithJsonArray([
    // 1. SETUP BLOCK
    {
        "type": "ks0258_setup",
        "message0": "⚙️ Setup Keyestudio Servo Shield | I2C: %1",
        "args0": [
            { "type": "field_input", "name": "ADDRESS", "text": "0x40" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 210,
        "tooltip": "Initialisiert das KS0258 16-Kanal Servo Shield mit 50Hz. Legt intern eine Tabelle für die Winkel an."
    },

    // 2. EINZEL SERVO (0-180°)
    {
        "type": "ks0258_servo_write",
        "message0": "Keyestudio Shield | Kanal %1 auf Winkel %2°",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 },
            { "type": "input_value", "name": "ANGLE", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Fährt den Servo sofort auf den Zielwinkel und merkt sich die Position."
    },

    // 3. ALLE SERVOS GLEICHZEITIG
    {
        "type": "ks0258_servo_all",
        "message0": "Keyestudio Shield | Alle 16 Kanäle auf Winkel %1°",
        "args0": [
            { "type": "input_value", "name": "ANGLE", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Setzt alle 16 Servos synchron auf denselben Winkel (z.B. 90° für die Grundstellung)."
    },

    // 4. SERVO RAMPE (Sanfte Bewegung)
    {
        "type": "ks0258_servo_ramp",
        "message0": "Keyestudio Shield Rampe | Kanal %1 Ziel-Winkel %2°",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 },
            { "type": "input_value", "name": "TARGET", "check": "Number" }
        ],
        "message1": "Schrittweite (°): %1 Pause (ms): %2",
        "args1": [
            { "type": "input_value", "name": "STEP", "check": "Number" },
            { "type": "input_value", "name": "DELAY", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Liest die Ist-Position aus dem internen Array und fährt den Servo sanft (blockierend) zum Ziel."
    },

    // 5. SERVO TRENNEN (Stromlos / Relax)
    {
        "type": "ks0258_servo_detach",
        "message0": "Keyestudio Shield | Kanal %1 freigeben (stromlos)",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Schaltet das PWM-Signal ab. Der Servo wird weich, brummt nicht und spart Strom."
    },

    // 6. SERVO AKTIVIEREN (Haltekraft)
    {
        "type": "ks0258_servo_attach",
        "message0": "Keyestudio Shield | Kanal %1 aktivieren (Haltekraft)",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Gibt dem Servo wieder das PWM-Signal der zuletzt gemerkten Position."
    },

    // 7. IST-WINKEL ABFRAGEN (Runder Output-Block)
    {
        "type": "ks0258_get_position",
        "message0": "Ist-Winkel von Shield Kanal %1",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 }
        ],
        "output": "Number",
        "colour": 180,
        "tooltip": "Gibt den zuletzt angefahrenen Winkel (0-180) dieses Kanals aus dem Speicher zurück."
    },

    // 8. PWM / LED MODUS (0-255)
    {
        "type": "ks0258_pwm_write",
        "message0": "Keyestudio Shield PWM (LED) | Kanal %1 Wert (0-255): %2",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 },
            { "type": "input_value", "name": "VAL", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 160,
        "tooltip": "Nutzt den Shield-Kanal, um z.B. eine LED zu dimmen (0=Aus, 255=Voll an)."
    }
]);


// =======================================================================
// DEZENTRALE SCANNER (Hardware Registrierung)
// =======================================================================
ArduinoGenerator.hardwareScanners['ks0258_setup'] = function(block) {
    const addr = block.getFieldValue('ADDRESS');
    
    ArduinoGenerator.includes_.add('#include <Wire.h>');
    ArduinoGenerator.includes_.add('#include <Adafruit_PWMServoDriver.h>');
    
    ArduinoGenerator.globals_.add(`Adafruit_PWMServoDriver ks_pwm = Adafruit_PWMServoDriver(${addr});`);
    
    // Defines für die Pulsweiten (besser als const int für den Kompiler bei Macros)
    ArduinoGenerator.globals_.add(`#define KS_SERVOMIN  150 // Minimale Pulsweite (0°)`);
    ArduinoGenerator.globals_.add(`#define KS_SERVOMAX  600 // Maximale Pulsweite (180°)`);
    
    // Array, um die Positionen aller 16 Servos zu speichern (als Gedächtnis für Rampen & Abfragen)
    ArduinoGenerator.globals_.add(`int ks_servoPos[16];`);
    
    // Im Setup: Initialisieren, Frequenz auf Servo-Standard (50Hz) setzen und Array füllen
    ArduinoGenerator.autoSetup_.push(`  ks_pwm.begin();\n  ks_pwm.setPWMFreq(50);\n`);
    ArduinoGenerator.autoSetup_.push(`  for(int i=0; i<16; i++) { ks_servoPos[i] = 90; }\n`);
};


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

ArduinoGenerator.forBlock['ks0258_setup'] = function(block) {
    return `  // Keyestudio KS0258 Shield wurde initialisiert\n`;
};

ArduinoGenerator.forBlock['ks0258_servo_write'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const angle = ArduinoGenerator.valueToCode(block, 'ANGLE', 0) || '90';
    return `  ks_pwm.setPWM(${channel}, 0, map(${angle}, 0, 180, KS_SERVOMIN, KS_SERVOMAX));\n  ks_servoPos[${channel}] = ${angle};\n`;
};

ArduinoGenerator.forBlock['ks0258_servo_all'] = function(block) {
    const angle = ArduinoGenerator.valueToCode(block, 'ANGLE', 0) || '90';
    let code = `  for(int i=0; i<16; i++) {\n`;
    code += `    ks_pwm.setPWM(i, 0, map(${angle}, 0, 180, KS_SERVOMIN, KS_SERVOMAX));\n`;
    code += `    ks_servoPos[i] = ${angle};\n`;
    code += `  }\n`;
    return code;
};

ArduinoGenerator.forBlock['ks0258_servo_ramp'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const target = ArduinoGenerator.valueToCode(block, 'TARGET', 0) || '90';
    const step = ArduinoGenerator.valueToCode(block, 'STEP', 0) || '1';
    const delayTime = ArduinoGenerator.valueToCode(block, 'DELAY', 0) || '15';
    
    let code = `  // --- KS0258 Shield Rampe (Kanal ${channel}) ---\n`;
    code += `  int _ks_target_${channel} = ${target};\n`;
    code += `  int _ks_step_${channel} = ${step};\n`;
    code += `  if (ks_servoPos[${channel}] < _ks_target_${channel}) {\n`;
    code += `    for (int a = ks_servoPos[${channel}]; a <= _ks_target_${channel}; a += _ks_step_${channel}) {\n`;
    code += `      ks_pwm.setPWM(${channel}, 0, map(a, 0, 180, KS_SERVOMIN, KS_SERVOMAX));\n`;
    code += `      delay(${delayTime});\n`;
    code += `    }\n`;
    code += `  } else {\n`;
    code += `    for (int a = ks_servoPos[${channel}]; a >= _ks_target_${channel}; a -= _ks_step_${channel}) {\n`;
    code += `      ks_pwm.setPWM(${channel}, 0, map(a, 0, 180, KS_SERVOMIN, KS_SERVOMAX));\n`;
    code += `      delay(${delayTime});\n`;
    code += `    }\n`;
    code += `  }\n`;
    code += `  // Zielsichere finale Position setzen und abspeichern\n`;
    code += `  ks_pwm.setPWM(${channel}, 0, map(_ks_target_${channel}, 0, 180, KS_SERVOMIN, KS_SERVOMAX));\n`;
    code += `  ks_servoPos[${channel}] = _ks_target_${channel};\n`;
    
    return code;
};

ArduinoGenerator.forBlock['ks0258_servo_detach'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    return `  ks_pwm.setPWM(${channel}, 0, 4096); // Schaltet das PWM Signal auf Kanal ${channel} ab\n`; // Bei PCA9685 schaltet der Wert 4096 (Bit 12) den Pin komplett aus
};

ArduinoGenerator.forBlock['ks0258_servo_attach'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    return `  ks_pwm.setPWM(${channel}, 0, map(ks_servoPos[${channel}], 0, 180, KS_SERVOMIN, KS_SERVOMAX)); // Verbindet Servo wieder auf letzte Pos\n`;
};

ArduinoGenerator.forBlock['ks0258_get_position'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    return [`ks_servoPos[${channel}]`, 0]; // Liest aus dem Array
};

ArduinoGenerator.forBlock['ks0258_pwm_write'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const val = ArduinoGenerator.valueToCode(block, 'VAL', 0) || '0';
    // Mappt den typischen Arduino-Wert (0-255) auf den 12-Bit-Wert des Shields (0-4095)
    return `  ks_pwm.setPWM(${channel}, 0, map(${val}, 0, 255, 0, 4095));\n`;
};