Blockly.defineBlocksWithJsonArray([
    // 1. SETUP (Grundmodul)
    {
        "type": "pca9685_setup",
        "message0": "Setup PCA9685 Shield | I2C Adresse: %1 Frequenz: %2 Hz",
        "args0": [
            { "type": "field_input", "name": "ADDRESS", "text": "0x40" },
            { "type": "field_number", "name": "FREQ", "value": 50 }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 210,
        "tooltip": "Initialisiert das PCA9685 Modul und erstellt die Positions-Liste."
    },

    // 2. STARTWERT (Im Setup zu verwenden)
    {
        "type": "pca9685_start_pos",
        "message0": "PCA9685 Startwert festlegen | 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 auf die Parkposition und trägt den Wert als Ist-Zustand in die Liste ein."
    },

    // 3. STANDARD SERVO (Aus dem Bild: Springt sofort dorthin)
    {
        "type": "pca9685_servo_180",
        "message0": "PCA9685 Servo (0-180°) | Kanal %1 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 neue Position."
    },

    // 4. SERVO RAMPE (Langsam fahren mit Delay)
    {
        "type": "pca9685_servo_ramp",
        "message0": "PCA9685 Servo 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 der Liste und fährt sanft zum Soll-Winkel."
    },

    // 5. SERVO TRENNEN (Stromlos)
    {
        "type": "pca9685_servo_detach",
        "message0": "PCA9685 Servo trennen (Stromlos) | Kanal %1",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Schaltet das PWM-Signal für diesen Kanal ab. Der Servo wird weich."
    },

    // 6. SERVO VERBINDEN (Haltekraft)
    {
        "type": "pca9685_servo_attach",
        "message0": "PCA9685 Servo verbinden (Haltekraft) | Kanal %1",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Holt sich die letzte Position aus der Liste und bestromt den Servo wieder auf exakt diesem Winkel."
    },

    // 7. CONTINUOUS SERVO (360)
    {
        "type": "pca9685_servo_360",
        "message0": "PCA9685 360° Servo | Kanal %1 Wert %2",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 },
            { "type": "input_value", "name": "SPEED", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 180,
        "tooltip": "Steuert einen 360° Servo. 90 = Stopp, 0 = Links, 180 = Rechts."
    },

    // 8. PWM OUTPUT (0-255)
    {
        "type": "pca9685_pwm",
        "message0": "PCA9685 PWM | Kanal %1 Wert (0-255): %2",
        "args0": [
            { "type": "field_number", "name": "CHANNEL", "value": 0, "min": 0, "max": 15 },
            { "type": "input_value", "name": "PWM_VAL", "check": "Number" }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 160,
        "tooltip": "Gibt ein reines PWM-Signal (0-255) am PCA9685 aus."
    }
]);

// --- SCANNERS (Globale Definitionen & Setup) ---
ArduinoGenerator.hardwareScanners['pca9685_setup'] = function(block) {
    const addr = block.getFieldValue('ADDRESS');
    const freq = block.getFieldValue('FREQ');
    
    ArduinoGenerator.includes_.add('#include <Wire.h>');
    ArduinoGenerator.includes_.add('#include <Adafruit_PWMServoDriver.h>');
    
    ArduinoGenerator.globals_.add(`Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(${addr});`);
    ArduinoGenerator.globals_.add(`#define SERVOMIN  150 // Minimale Pulsweite (0°)`);
    ArduinoGenerator.globals_.add(`#define SERVOMAX  600 // Maximale Pulsweite (180°)`);
    
    // HIER IST DAS GEDÄCHTNIS: Das Array für die 16 Servopositionen
    ArduinoGenerator.globals_.add(`int pca_currentPos[16];`);
    
    // Initialisierung im Setup
    ArduinoGenerator.autoSetup_.push(`  pwm.begin();\n  pwm.setPWMFreq(${freq});\n`);
    // Standardmäßig nehmen wir an, dass alle Servos bei 90 Grad stehen, falls kein Startwert gesetzt wird
    ArduinoGenerator.autoSetup_.push(`  for(int i=0; i<16; i++) { pca_currentPos[i] = 90; }\n`);
};

// --- GENERATOREN ---

ArduinoGenerator.forBlock['pca9685_setup'] = function(block) {
    return '';
};

// Startwert im Setup setzen
ArduinoGenerator.forBlock['pca9685_start_pos'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const angle = ArduinoGenerator.valueToCode(block, 'ANGLE', 0) || '90';
    return `  pwm.setPWM(${channel}, 0, map(${angle}, 0, 180, SERVOMIN, SERVOMAX));\n  pca_currentPos[${channel}] = ${angle};\n`;
};

// Sofortige Bewegung (Standard)
ArduinoGenerator.forBlock['pca9685_servo_180'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const angle = ArduinoGenerator.valueToCode(block, 'ANGLE', 0) || '90';
    return `  pwm.setPWM(${channel}, 0, map(${angle}, 0, 180, SERVOMIN, SERVOMAX));\n  pca_currentPos[${channel}] = ${angle};\n`;
};

// Rampen-Bewegung (Aus Liste lesen, hochzählen, blockierend mit Delay)
ArduinoGenerator.forBlock['pca9685_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 = `  // --- PCA9685 Rampe (Kanal ${channel}) ---\n`;
    code += `  int _target_${channel} = ${target};\n`;
    code += `  int _step_${channel} = ${step};\n`;
    code += `  if (pca_currentPos[${channel}] < _target_${channel}) {\n`;
    code += `    for (int a = pca_currentPos[${channel}]; a <= _target_${channel}; a += _step_${channel}) {\n`;
    code += `      pwm.setPWM(${channel}, 0, map(a, 0, 180, SERVOMIN, SERVOMAX));\n`;
    code += `      delay(${delayTime});\n`;
    code += `    }\n`;
    code += `  } else {\n`;
    code += `    for (int a = pca_currentPos[${channel}]; a >= _target_${channel}; a -= _step_${channel}) {\n`;
    code += `      pwm.setPWM(${channel}, 0, map(a, 0, 180, SERVOMIN, SERVOMAX));\n`;
    code += `      delay(${delayTime});\n`;
    code += `    }\n`;
    code += `  }\n`;
    code += `  // Zielsichere finale Position setzen und abspeichern\n`;
    code += `  pwm.setPWM(${channel}, 0, map(_target_${channel}, 0, 180, SERVOMIN, SERVOMAX));\n`;
    code += `  pca_currentPos[${channel}] = _target_${channel};\n`;
    
    return code;
};

// Servo trennen (Puls auf 0 setzen)
ArduinoGenerator.forBlock['pca9685_servo_detach'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    return `  pwm.setPWM(${channel}, 0, 0); // Schaltet das Signal auf Kanal ${channel} ab\n`;
};

// Servo verbinden (Letzte Position aus Liste anfahren)
ArduinoGenerator.forBlock['pca9685_servo_attach'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    return `  pwm.setPWM(${channel}, 0, map(pca_currentPos[${channel}], 0, 180, SERVOMIN, SERVOMAX)); // Verbindet Servo wieder auf letzte Pos\n`;
};

// 360 Grad Servo
ArduinoGenerator.forBlock['pca9685_servo_360'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const speed = ArduinoGenerator.valueToCode(block, 'SPEED', 0) || '90';
    return `  pwm.setPWM(${channel}, 0, map(${speed}, 0, 180, SERVOMIN, SERVOMAX));\n`;
};

// PWM Ausgang
ArduinoGenerator.forBlock['pca9685_pwm'] = function(block) {
    const channel = block.getFieldValue('CHANNEL');
    const pwmVal = ArduinoGenerator.valueToCode(block, 'PWM_VAL', 0) || '0';
    return `  pwm.setPWM(${channel}, 0, map(${pwmVal}, 0, 255, 0, 4095));\n`;
};