#!/usr/bin/env python3
"""Generate 48 factory presets (12 banks x 4 presets) for Pi Multi-FX Pedal.

Replaces ALL existing factory presets in presets/factory/.
"""

import json
import os
import shutil

FACTORY_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "presets", "factory")

# ── Banks ──────────────────────────────────────────────────────────────
BANKS = [
    {"number": 0, "name": "Classic Rock"},
    {"number": 1, "name": "Punk"},
    {"number": 2, "name": "Metal"},
    {"number": 3, "name": "Hardcore"},
    {"number": 4, "name": "Emo"},
    {"number": 5, "name": "Midwest Emo"},
    {"number": 6, "name": "Djent"},
    {"number": 7, "name": "Acoustic"},
    {"number": 8, "name": "Grunge"},
    {"number": 9, "name": "Alternative Rock"},
    {"number": 10, "name": "Garage Rock"},
    {"number": 11, "name": "Pop"},
]

# ── IR path shortcuts ─────────────────────────────────────────────────
IR = {
    "vintage": "~/.pedal/irs/vintage-1x12.wav",
    "british": "~/.pedal/irs/british-4x12.wav",
    "american": "~/.pedal/irs/american-2x12.wav",
    "modern": "~/.pedal/irs/modern-4x12.wav",
    "jazz": "~/.pedal/irs/jazz-1x15.wav",
    "boutique": "~/.pedal/irs/boutique-1x12.wav",
    "mini": "~/.pedal/irs/mini-1x8.wav",
}

# ── Helper builders ────────────────────────────────────────────────────

def noise_gate(threshold=0.01):
    return {"fx_type": "noise_gate", "enabled": True, "bypass": False,
            "params": {"threshold": threshold}, "nam_model_path": "", "ir_file_path": ""}

def compressor(threshold=0.3, ratio=4.0, gain=0.8):
    return {"fx_type": "compressor", "enabled": True, "bypass": False,
            "params": {"threshold": threshold, "ratio": ratio, "gain": gain},
            "nam_model_path": "", "ir_file_path": ""}

def boost(gain_db=6.0):
    return {"fx_type": "boost", "enabled": True, "bypass": False,
            "params": {"gain_db": gain_db}, "nam_model_path": "", "ir_file_path": ""}

def overdrive(drive=0.5, gain=0.7, tone=0.5):
    return {"fx_type": "overdrive", "enabled": True, "bypass": False,
            "params": {"drive": drive, "tone": tone, "gain": gain},
            "nam_model_path": "", "ir_file_path": ""}

def distortion(drive=0.7, gain=0.5):
    return {"fx_type": "distortion", "enabled": True, "bypass": False,
            "params": {"drive": drive, "gain": gain},
            "nam_model_path": "", "ir_file_path": ""}

def fuzz(gain=0.6):
    return {"fx_type": "fuzz", "enabled": True, "bypass": False,
            "params": {"gain": gain}, "nam_model_path": "", "ir_file_path": ""}

def eq(bass=0.5, mid=0.5, treble=0.5):
    return {"fx_type": "eq", "enabled": True, "bypass": False,
            "params": {"bass": bass, "mid": mid, "treble": treble},
            "nam_model_path": "", "ir_file_path": ""}

def ir_cab(ir_path):
    return {"fx_type": "ir_cab", "enabled": True, "bypass": False,
            "params": {"wet": 1.0, "dry": 0.0},
            "nam_model_path": "", "ir_file_path": ir_path}

def delay(time=400.0, feedback=0.3, mix=0.25):
    return {"fx_type": "delay", "enabled": True, "bypass": False,
            "params": {"time": time, "feedback": feedback, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

def reverb(decay=0.4, mix=0.25):
    return {"fx_type": "reverb", "enabled": True, "bypass": False,
            "params": {"decay": decay, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

def chorus(rate=0.35, depth=0.5, mix=0.3):
    return {"fx_type": "chorus", "enabled": True, "bypass": False,
            "params": {"rate": rate, "depth": depth, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

def phaser(rate=0.3, depth=0.5, feedback=0.3):
    return {"fx_type": "phaser", "enabled": True, "bypass": False,
            "params": {"rate": rate, "depth": depth, "feedback": feedback},
            "nam_model_path": "", "ir_file_path": ""}

def flanger(rate=0.2, depth=0.4, feedback=0.3):
    return {"fx_type": "flanger", "enabled": True, "bypass": False,
            "params": {"rate": rate, "depth": depth, "feedback": feedback},
            "nam_model_path": "", "ir_file_path": ""}

def tremolo(rate=3.0, depth=0.4):
    return {"fx_type": "tremolo", "enabled": True, "bypass": False,
            "params": {"rate": rate, "depth": depth},
            "nam_model_path": "", "ir_file_path": ""}

def volume(level=0.85):
    return {"fx_type": "volume", "enabled": True, "bypass": False,
            "params": {"level": level}, "nam_model_path": "", "ir_file_path": ""}

def octaver(mix=0.4):
    return {"fx_type": "octaver", "enabled": True, "bypass": False,
            "params": {"mix": mix}, "nam_model_path": "", "ir_file_path": ""}

# ── Preset definitions per bank ────────────────────────────────────────

PRESETS = {
    0: [  # Classic Rock
        {
            "name": "Brown Sound Crunch",
            "master_volume": 0.75,
            "chain": [
                noise_gate(0.015),
                overdrive(0.55, 0.75, 0.5),
                eq(0.55, 0.35, 0.65),
                delay(380, 0.25, 0.2),
                ir_cab(IR["british"]),
                volume(0.78),
            ],
        },
        {
            "name": "Singing Lead",
            "master_volume": 0.85,
            "chain": [
                noise_gate(0.02),
                compressor(0.35, 3.5, 1.1),
                overdrive(0.7, 0.65, 0.6),
                distortion(0.5, 0.5),
                eq(0.5, 0.25, 0.75),
                delay(450, 0.35, 0.3),
                reverb(0.5, 0.25),
                ir_cab(IR["british"]),
                volume(0.88),
            ],
        },
        {
            "name": "Sparkling Clean",
            "master_volume": 0.78,
            "chain": [
                noise_gate(0.008),
                compressor(0.25, 4.0, 0.85),
                eq(0.45, 0.5, 0.65),
                chorus(0.3, 0.45, 0.3),
                reverb(0.35, 0.2),
                ir_cab(IR["vintage"]),
                volume(0.82),
            ],
        },
        {
            "name": "Hard Rock Pounder",
            "master_volume": 0.7,
            "chain": [
                noise_gate(0.025),
                boost(8.0),
                distortion(0.75, 0.45),
                eq(0.6, 0.25, 0.7),
                ir_cab(IR["modern"]),
                volume(0.72),
            ],
        },
    ],
    1: [  # Punk
        {
            "name": "Fast Riff Machine",
            "master_volume": 0.72,
            "chain": [
                noise_gate(0.02),
                boost(6.0),
                overdrive(0.6, 0.7, 0.45),
                eq(0.5, 0.3, 0.7),
                ir_cab(IR["british"]),
                volume(0.75),
            ],
        },
        {
            "name": "Snotty Lead",
            "master_volume": 0.82,
            "chain": [
                noise_gate(0.015),
                overdrive(0.4, 0.85, 0.4),
                distortion(0.65, 0.5),
                eq(0.4, 0.35, 0.8),
                delay(350, 0.2, 0.2),
                ir_cab(IR["british"]),
                volume(0.85),
            ],
        },
        {
            "name": "Jangle Pop Clean",
            "master_volume": 0.76,
            "chain": [
                noise_gate(0.008),
                compressor(0.3, 4.5, 0.75),
                eq(0.4, 0.55, 0.7),
                chorus(0.4, 0.35, 0.25),
                reverb(0.3, 0.2),
                ir_cab(IR["american"]),
                volume(0.8),
            ],
        },
        {
            "name": "Hardcore Attack",
            "master_volume": 0.68,
            "chain": [
                noise_gate(0.03),
                boost(9.0),
                distortion(0.8, 0.4),
                eq(0.55, 0.2, 0.75),
                ir_cab(IR["modern"]),
                volume(0.7),
            ],
        },
    ],
    2: [  # Metal
        {
            "name": "Chug Chug",
            "master_volume": 0.65,
            "chain": [
                noise_gate(0.035),
                boost(10.0),
                distortion(0.85, 0.35),
                eq(0.65, 0.15, 0.7),
                ir_cab(IR["modern"]),
                volume(0.68),
            ],
        },
        {
            "name": "Scream Lead",
            "master_volume": 0.82,
            "chain": [
                noise_gate(0.03),
                compressor(0.4, 3.0, 1.3),
                boost(8.0),
                distortion(0.75, 0.4),
                eq(0.5, 0.2, 0.85),
                delay(420, 0.3, 0.28),
                reverb(0.4, 0.2),
                ir_cab(IR["modern"]),
                volume(0.86),
            ],
        },
        {
            "name": "Crystal Clean",
            "master_volume": 0.75,
            "chain": [
                noise_gate(0.008),
                compressor(0.2, 5.0, 0.7),
                eq(0.4, 0.5, 0.65),
                chorus(0.3, 0.5, 0.35),
                reverb(0.45, 0.3),
                ir_cab(IR["vintage"]),
                volume(0.78),
            ],
        },
        {
            "name": "Doom Descent",
            "master_volume": 0.6,
            "chain": [
                noise_gate(0.04),
                boost(12.0),
                fuzz(0.75),
                distortion(0.9, 0.3),
                eq(0.7, 0.1, 0.65),
                ir_cab(IR["modern"]),
                volume(0.62),
            ],
        },
    ],
    3: [  # Hardcore
        {
            "name": "Punch Drunk",
            "master_volume": 0.7,
            "chain": [
                noise_gate(0.025),
                overdrive(0.5, 0.8, 0.4),
                distortion(0.6, 0.5),
                eq(0.55, 0.25, 0.7),
                ir_cab(IR["modern"]),
                volume(0.73),
            ],
        },
        {
            "name": "Vein Lead",
            "master_volume": 0.8,
            "chain": [
                noise_gate(0.02),
                compressor(0.35, 3.5, 1.0),
                boost(7.0),
                overdrive(0.65, 0.6, 0.5),
                eq(0.5, 0.2, 0.8),
                delay(380, 0.25, 0.25),
                ir_cab(IR["british"]),
                volume(0.83),
            ],
        },
        {
            "name": "Breather Clean",
            "master_volume": 0.74,
            "chain": [
                noise_gate(0.008),
                compressor(0.28, 4.0, 0.8),
                eq(0.45, 0.55, 0.6),
                reverb(0.4, 0.25),
                ir_cab(IR["american"]),
                volume(0.76),
            ],
        },
        {
            "name": "Pit Stomp",
            "master_volume": 0.66,
            "chain": [
                noise_gate(0.035),
                boost(9.0),
                distortion(0.85, 0.35),
                eq(0.6, 0.15, 0.75),
                ir_cab(IR["modern"]),
                volume(0.68),
            ],
        },
    ],
    4: [  # Emo
        {
            "name": "Twinkle Crunch",
            "master_volume": 0.72,
            "chain": [
                noise_gate(0.012),
                compressor(0.3, 4.0, 0.8),
                overdrive(0.35, 0.8, 0.55),
                chorus(0.4, 0.3, 0.2),
                eq(0.4, 0.6, 0.65),
                ir_cab(IR["american"]),
                volume(0.75),
            ],
        },
        {
            "name": "Heartstring Lead",
            "master_volume": 0.84,
            "chain": [
                noise_gate(0.015),
                compressor(0.3, 3.5, 1.0),
                overdrive(0.6, 0.7, 0.5),
                eq(0.45, 0.35, 0.75),
                delay(480, 0.4, 0.35),
                reverb(0.6, 0.3),
                ir_cab(IR["american"]),
                volume(0.86),
            ],
        },
        {
            "name": "Diary Pages",
            "master_volume": 0.76,
            "chain": [
                noise_gate(0.008),
                compressor(0.25, 5.0, 0.7),
                eq(0.35, 0.6, 0.55),
                reverb(0.55, 0.3),
                ir_cab(IR["vintage"]),
                volume(0.78),
            ],
        },
        {
            "name": "Pop Core",
            "master_volume": 0.7,
            "chain": [
                noise_gate(0.02),
                boost(7.0),
                distortion(0.7, 0.45),
                eq(0.5, 0.25, 0.7),
                delay(350, 0.2, 0.15),
                ir_cab(IR["british"]),
                volume(0.72),
            ],
        },
    ],
    5: [  # Midwest Emo
        {
            "name": "Mathy Tappy",
            "master_volume": 0.72,
            "chain": [
                noise_gate(0.01),
                compressor(0.3, 4.5, 0.75),
                overdrive(0.3, 0.85, 0.5),
                eq(0.4, 0.55, 0.6),
                delay(400, 0.2, 0.15),
                ir_cab(IR["american"]),
                volume(0.74),
            ],
        },
        {
            "name": "Emotive Swell",
            "master_volume": 0.82,
            "chain": [
                noise_gate(0.012),
                compressor(0.28, 4.0, 0.9),
                overdrive(0.5, 0.75, 0.45),
                eq(0.4, 0.4, 0.7),
                delay(500, 0.35, 0.3),
                reverb(0.5, 0.3),
                ir_cab(IR["american"]),
                volume(0.84),
            ],
        },
        {
            "name": "Fingerpicked Porch",
            "master_volume": 0.75,
            "chain": [
                noise_gate(0.006),
                compressor(0.2, 5.0, 0.7),
                eq(0.35, 0.65, 0.55),
                chorus(0.25, 0.35, 0.2),
                reverb(0.4, 0.22),
                ir_cab(IR["boutique"]),
                volume(0.77),
            ],
        },
        {
            "name": "Power Chord Wall",
            "master_volume": 0.68,
            "chain": [
                noise_gate(0.02),
                overdrive(0.55, 0.7, 0.45),
                distortion(0.6, 0.5),
                eq(0.5, 0.3, 0.65),
                ir_cab(IR["british"]),
                volume(0.7),
            ],
        },
    ],
    6: [  # Djent
        {
            "name": "Machine Gun",
            "master_volume": 0.62,
            "chain": [
                noise_gate(0.04),
                compressor(0.4, 6.0, 1.0),
                boost(12.0),
                distortion(0.85, 0.3),
                eq(0.7, 0.1, 0.8),
                ir_cab(IR["modern"]),
                volume(0.65),
            ],
        },
        {
            "name": "Polyphonic Lead",
            "master_volume": 0.8,
            "chain": [
                noise_gate(0.025),
                compressor(0.35, 4.0, 1.1),
                overdrive(0.6, 0.6, 0.55),
                eq(0.55, 0.2, 0.8),
                delay(440, 0.3, 0.28),
                reverb(0.45, 0.2),
                ir_cab(IR["modern"]),
                volume(0.82),
            ],
        },
        {
            "name": "Clean Arpeggio",
            "master_volume": 0.76,
            "chain": [
                noise_gate(0.008),
                compressor(0.25, 5.0, 0.7),
                eq(0.4, 0.5, 0.6),
                chorus(0.3, 0.4, 0.3),
                delay(480, 0.25, 0.2),
                reverb(0.4, 0.25),
                ir_cab(IR["american"]),
                volume(0.78),
            ],
        },
        {
            "name": "Syncopated Riff",
            "master_volume": 0.6,
            "chain": [
                noise_gate(0.045),
                boost(10.0),
                fuzz(0.7),
                distortion(0.8, 0.3),
                eq(0.65, 0.1, 0.75),
                ir_cab(IR["modern"]),
                volume(0.62),
            ],
        },
    ],
    7: [  # Acoustic
        {
            "name": "Body Strum",
            "master_volume": 0.78,
            "chain": [
                noise_gate(0.005),
                compressor(0.25, 4.5, 0.65),
                eq(0.5, 0.6, 0.55),
                reverb(0.35, 0.2),
                ir_cab(IR["boutique"]),
                volume(0.8),
            ],
        },
        {
            "name": "Fingerpicking Lead",
            "master_volume": 0.82,
            "chain": [
                noise_gate(0.005),
                compressor(0.2, 5.0, 0.7),
                eq(0.4, 0.65, 0.5),
                delay(380, 0.2, 0.18),
                reverb(0.45, 0.25),
                ir_cab(IR["boutique"]),
                volume(0.84),
            ],
        },
        {
            "name": "Ambient Soundscape",
            "master_volume": 0.8,
            "chain": [
                noise_gate(0.005),
                compressor(0.3, 4.0, 0.8),
                eq(0.4, 0.5, 0.55),
                chorus(0.2, 0.5, 0.4),
                reverb(0.7, 0.4),
                ir_cab(IR["jazz"]),
                volume(0.82),
            ],
        },
        {
            "name": "Percussive Slap",
            "master_volume": 0.74,
            "chain": [
                noise_gate(0.006),
                compressor(0.35, 6.0, 0.6),
                boost(4.0),
                eq(0.55, 0.4, 0.65),
                ir_cab(IR["american"]),
                volume(0.76),
            ],
        },
    ],
    8: [  # Grunge
        {
            "name": "Fuzz Festival",
            "master_volume": 0.7,
            "chain": [
                noise_gate(0.015),
                overdrive(0.5, 0.75, 0.4),
                fuzz(0.6),
                eq(0.55, 0.2, 0.7),
                ir_cab(IR["british"]),
                volume(0.72),
            ],
        },
        {
            "name": "Biting Solo",
            "master_volume": 0.82,
            "chain": [
                noise_gate(0.02),
                boost(7.0),
                distortion(0.65, 0.5),
                eq(0.35, 0.15, 0.85),
                delay(400, 0.3, 0.28),
                ir_cab(IR["british"]),
                volume(0.85),
            ],
        },
        {
            "name": "Grunge Clean",
            "master_volume": 0.75,
            "chain": [
                noise_gate(0.008),
                compressor(0.3, 4.0, 0.8),
                overdrive(0.2, 0.9, 0.5),
                phaser(0.25, 0.4, 0.3),
                eq(0.45, 0.5, 0.6),
                ir_cab(IR["vintage"]),
                volume(0.77),
            ],
        },
        {
            "name": "Wall of Noise",
            "master_volume": 0.65,
            "chain": [
                noise_gate(0.025),
                boost(10.0),
                fuzz(0.8),
                distortion(0.7, 0.35),
                eq(0.6, 0.1, 0.75),
                ir_cab(IR["modern"]),
                volume(0.67),
            ],
        },
    ],
    9: [  # Alternative Rock
        {
            "name": "Indie Crunch",
            "master_volume": 0.74,
            "chain": [
                noise_gate(0.012),
                overdrive(0.45, 0.78, 0.55),
                eq(0.5, 0.4, 0.65),
                ir_cab(IR["american"]),
                volume(0.76),
            ],
        },
        {
            "name": "Quirky Lead",
            "master_volume": 0.84,
            "chain": [
                noise_gate(0.015),
                compressor(0.3, 3.5, 1.0),
                overdrive(0.55, 0.65, 0.5),
                flanger(0.15, 0.35, 0.25),
                eq(0.45, 0.3, 0.75),
                delay(420, 0.3, 0.28),
                ir_cab(IR["american"]),
                volume(0.86),
            ],
        },
        {
            "name": "Jangle Box",
            "master_volume": 0.76,
            "chain": [
                noise_gate(0.008),
                compressor(0.25, 4.5, 0.75),
                eq(0.4, 0.55, 0.65),
                tremolo(4.0, 0.35),
                reverb(0.3, 0.2),
                ir_cab(IR["american"]),
                volume(0.78),
            ],
        },
        {
            "name": "Alt Heavy",
            "master_volume": 0.68,
            "chain": [
                noise_gate(0.025),
                boost(8.0),
                distortion(0.75, 0.4),
                octaver(0.3),
                eq(0.55, 0.2, 0.75),
                ir_cab(IR["modern"]),
                volume(0.7),
            ],
        },
    ],
    10: [  # Garage Rock
        {
            "name": "Lo-Fi Crunch",
            "master_volume": 0.72,
            "chain": [
                noise_gate(0.015),
                overdrive(0.6, 0.7, 0.35),
                eq(0.5, 0.3, 0.55),
                ir_cab(IR["mini"]),
                volume(0.74),
            ],
        },
        {
            "name": "Fuzzed Out",
            "master_volume": 0.8,
            "chain": [
                noise_gate(0.01),
                boost(6.0),
                fuzz(0.7),
                eq(0.45, 0.25, 0.65),
                delay(300, 0.3, 0.25),
                ir_cab(IR["british"]),
                volume(0.82),
            ],
        },
        {
            "name": "Raw Clean",
            "master_volume": 0.78,
            "chain": [
                noise_gate(0.006),
                eq(0.45, 0.55, 0.5),
                tremolo(2.5, 0.3),
                reverb(0.3, 0.18),
                ir_cab(IR["vintage"]),
                volume(0.8),
            ],
        },
        {
            "name": "Sludge Fuzz",
            "master_volume": 0.62,
            "chain": [
                noise_gate(0.03),
                boost(12.0),
                fuzz(0.85),
                distortion(0.7, 0.3),
                eq(0.65, 0.1, 0.6),
                ir_cab(IR["modern"]),
                volume(0.64),
            ],
        },
    ],
    11: [  # Pop
        {
            "name": "Clean Pop",
            "master_volume": 0.78,
            "chain": [
                noise_gate(0.006),
                compressor(0.28, 4.5, 0.7),
                overdrive(0.2, 0.9, 0.6),
                eq(0.45, 0.5, 0.6),
                ir_cab(IR["american"]),
                volume(0.8),
            ],
        },
        {
            "name": "Catchy Hook",
            "master_volume": 0.84,
            "chain": [
                noise_gate(0.01),
                compressor(0.3, 4.0, 0.9),
                overdrive(0.4, 0.8, 0.5),
                chorus(0.35, 0.4, 0.3),
                delay(380, 0.25, 0.22),
                ir_cab(IR["american"]),
                volume(0.86),
            ],
        },
        {
            "name": "Shimmer Clean",
            "master_volume": 0.8,
            "chain": [
                noise_gate(0.006),
                compressor(0.2, 5.0, 0.65),
                eq(0.35, 0.55, 0.65),
                chorus(0.3, 0.5, 0.35),
                reverb(0.5, 0.3),
                ir_cab(IR["vintage"]),
                volume(0.82),
            ],
        },
        {
            "name": "Pop Punk",
            "master_volume": 0.72,
            "chain": [
                noise_gate(0.018),
                overdrive(0.5, 0.75, 0.45),
                distortion(0.55, 0.55),
                eq(0.5, 0.3, 0.7),
                delay(320, 0.15, 0.12),
                ir_cab(IR["british"]),
                volume(0.74),
            ],
        },
    ],
}

# ── Generate all files ─────────────────────────────────────────────────

def generate():
    # Wipe existing factory dir
    if os.path.exists(FACTORY_DIR):
        # Remove all bank dirs but keep irs/
        for entry in os.listdir(FACTORY_DIR):
            path = os.path.join(FACTORY_DIR, entry)
            if entry != "irs" and os.path.isdir(path):
                shutil.rmtree(path)
            elif entry != "irs" and os.path.isfile(path):
                os.remove(path)

    for bank in BANKS:
        num = bank["number"]
        bank_dir = os.path.join(FACTORY_DIR, f"bank_{num}")
        os.makedirs(bank_dir, exist_ok=True)

        # bank.json
        bank_json = {
            "number": num,
            "name": bank["name"],
            "preset_count": 4,
        }
        with open(os.path.join(bank_dir, "bank.json"), "w") as f:
            json.dump(bank_json, f, indent=2)
            f.write("\n")

        # 4 presets
        for prog in range(4):
            preset_data = PRESETS[num][prog]
            preset_json = {
                "name": preset_data["name"],
                "bank": num,
                "program": prog,
                "master_volume": preset_data["master_volume"],
                "tuner_enabled": False,
                "chain": preset_data["chain"],
                "midi_mappings": {},
            }
            path = os.path.join(bank_dir, f"preset_{prog}.json")
            with open(path, "w") as f:
                json.dump(preset_json, f, indent=2)
                f.write("\n")

    print(f"✅ Generated {len(BANKS) * 4} presets across {len(BANKS)} banks")
    for bank in BANKS:
        print(f"   Bank {bank['number']}: {bank['name']} — 4 presets")


if __name__ == "__main__":
    generate()
