#!/usr/bin/env python3
"""Generate factory presets for Keys, Vocals, and Backing Tracks channels.

Creates 3 banks × 4 presets per channel under presets/factory/<channel>/.
Bank numbers start at 21 for Keys, 24 for Vocals, 27 for Backing Tracks
to avoid collisions with the existing 0-20 factory bank range.
"""

import json
import os
import sys

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

# ── 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",
    "bass_thick": "~/.pedal/irs/bass-thick_classic.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 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, subtype=""):
    fx = {"fx_type": "reverb", "enabled": True, "bypass": False,
           "nam_model_path": "", "ir_file_path": ""}
    params = {"decay": decay, "mix": mix}
    if subtype:
        params["subtype"] = subtype
    fx["params"] = params
    return fx

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 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 pitch_shifter(semitones=0, mix=0.5):
    return {"fx_type": "pitch_shifter", "enabled": True, "bypass": False,
            "params": {"semitones": semitones, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

def stereo_widener(width=0.5, mix=0.5):
    return {"fx_type": "stereo_widener", "enabled": True, "bypass": False,
            "params": {"width": width, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

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

def high_pass_filter(cutoff=80.0):
    return {"fx_type": "high_pass_filter", "enabled": True, "bypass": False,
            "params": {"cutoff": cutoff},
            "nam_model_path": "", "ir_file_path": ""}

def low_pass_filter(cutoff=8000.0):
    return {"fx_type": "low_pass_filter", "enabled": True, "bypass": False,
            "params": {"cutoff": cutoff},
            "nam_model_path": "", "ir_file_path": ""}

def de_esser(threshold=0.5, reduction=0.4):
    return {"fx_type": "de_esser", "enabled": True, "bypass": False,
            "params": {"threshold": threshold, "reduction": reduction},
            "nam_model_path": "", "ir_file_path": ""}

def shimmer_reverb(decay=0.6, mix=0.3):
    return {"fx_type": "shimmer_reverb", "enabled": True, "bypass": False,
            "params": {"decay": decay, "mix": mix},
            "nam_model_path": "", "ir_file_path": ""}

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

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

def expander(threshold=0.2, ratio=2.0):
    return {"fx_type": "expander", "enabled": True, "bypass": False,
            "params": {"threshold": threshold, "ratio": ratio},
            "nam_model_path": "", "ir_file_path": ""}

# ── Channel definitions ─────────────────────────────────────────────────

CHANNELS = [
    {
        "slug": "keys",
        "label": "Keys",
        "bank_start": 21,
        "banks": [
            {
                "name": "Piano & Electric",
                "presets": [
                    {
                        "name": "Grand Piano Clean",
                        "master_volume": 0.82,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 5.0, 0.6),
                            eq(0.5, 0.5, 0.55),
                            reverb(0.35, 0.2, "hall"),
                            volume(0.85),
                        ],
                    },
                    {
                        "name": "Warm Rhodes",
                        "master_volume": 0.8,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.25, 4.0, 0.65),
                            chorus(0.3, 0.4, 0.25),
                            eq(0.45, 0.55, 0.5),
                            reverb(0.4, 0.22, "hall"),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "Wurli Punch",
                        "master_volume": 0.78,
                        "chain": [
                            noise_gate(0.008),
                            compressor(0.3, 4.5, 0.7),
                            tremolo(4.0, 0.3),
                            eq(0.55, 0.4, 0.6),
                            reverb(0.3, 0.18, "room"),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Stage EP Layer",
                        "master_volume": 0.82,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 5.0, 0.55),
                            stereo_widener(0.4, 0.3),
                            eq(0.4, 0.5, 0.6),
                            chorus(0.25, 0.35, 0.2),
                            reverb(0.45, 0.28, "hall"),
                            volume(0.84),
                        ],
                    },
                ],
            },
            {
                "name": "Synth Pads & Leads",
                "presets": [
                    {
                        "name": "Analog Pad",
                        "master_volume": 0.78,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.25, 4.5, 0.65),
                            stereo_widener(0.6, 0.4),
                            chorus(0.2, 0.45, 0.35),
                            auto_pan(0.15, 0.3),
                            reverb(0.55, 0.35, "hall"),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Brass Synth Lead",
                        "master_volume": 0.85,
                        "chain": [
                            noise_gate(0.01),
                            compressor(0.3, 3.5, 0.85),
                            boost(3.0),
                            eq(0.45, 0.35, 0.7),
                            delay(420, 0.25, 0.2),
                            reverb(0.4, 0.22, "hall"),
                            volume(0.88),
                        ],
                    },
                    {
                        "name": "Arp Texture",
                        "master_volume": 0.76,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 5.0, 0.55),
                            eq(0.4, 0.55, 0.65),
                            multi_tap_delay(300, 0.2, 0.3, 3),
                            reverb(0.5, 0.3, "hall"),
                            volume(0.78),
                        ],
                    },
                    {
                        "name": "Wobble Bass Synth",
                        "master_volume": 0.72,
                        "chain": [
                            noise_gate(0.012),
                            compressor(0.35, 6.0, 0.6),
                            low_pass_filter(2000.0),
                            eq(0.65, 0.25, 0.4),
                            reverb(0.2, 0.1, "room"),
                            volume(0.74),
                        ],
                    },
                ],
            },
            {
                "name": "Organ & Vintage Keys",
                "presets": [
                    {
                        "name": "B3 Rotary Slow",
                        "master_volume": 0.8,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 4.5, 0.65),
                            rotary_speaker(0.8, 0.4),
                            eq(0.5, 0.5, 0.55),
                            reverb(0.3, 0.15, "room"),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "B3 Rotary Fast",
                        "master_volume": 0.82,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 4.5, 0.7),
                            rotary_speaker(5.0, 0.5),
                            eq(0.45, 0.55, 0.5),
                            reverb(0.25, 0.12, "room"),
                            volume(0.84),
                        ],
                    },
                    {
                        "name": "Clavinet Funk",
                        "master_volume": 0.76,
                        "chain": [
                            noise_gate(0.008),
                            compressor(0.35, 5.0, 0.6),
                            eq(0.6, 0.3, 0.7),
                            phaser(0.2, 0.35, 0.2),
                            reverb(0.2, 0.1, "room"),
                            volume(0.78),
                        ],
                    },
                    {
                        "name": "Vox Continental",
                        "master_volume": 0.82,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.25, 4.0, 0.65),
                            eq(0.5, 0.45, 0.6),
                            tremolo(3.5, 0.3),
                            reverb(0.35, 0.18, "hall"),
                            volume(0.84),
                        ],
                    },
                ],
            },
        ],
    },
    {
        "slug": "vocals",
        "label": "Vocals",
        "bank_start": 24,
        "banks": [
            {
                "name": "Lead Vocals",
                "presets": [
                    {
                        "name": "Vocal Standard",
                        "master_volume": 0.82,
                        "chain": [
                            high_pass_filter(80.0),
                            de_esser(0.5, 0.35),
                            compressor(0.25, 4.0, 0.7),
                            eq(0.45, 0.55, 0.55),
                            reverb(0.35, 0.22, "hall"),
                            volume(0.85),
                        ],
                    },
                    {
                        "name": "Warm Lead",
                        "master_volume": 0.85,
                        "chain": [
                            high_pass_filter(75.0),
                            de_esser(0.45, 0.4),
                            compressor(0.2, 4.5, 0.75),
                            eq(0.5, 0.5, 0.45),
                            reverb(0.4, 0.25, "hall"),
                            delay(380, 0.2, 0.15),
                            volume(0.88),
                        ],
                    },
                    {
                        "name": "Big Ballad",
                        "master_volume": 0.84,
                        "chain": [
                            high_pass_filter(70.0),
                            de_esser(0.5, 0.3),
                            compressor(0.22, 5.0, 0.8),
                            eq(0.45, 0.5, 0.5),
                            shimmer_reverb(0.55, 0.3),
                            delay(450, 0.3, 0.2),
                            volume(0.86),
                        ],
                    },
                    {
                        "name": "Dry & Present",
                        "master_volume": 0.82,
                        "chain": [
                            high_pass_filter(90.0),
                            de_esser(0.55, 0.35),
                            compressor(0.28, 3.5, 0.85),
                            eq(0.4, 0.6, 0.55),
                            expander(0.15, 1.5),
                            volume(0.84),
                        ],
                    },
                ],
            },
            {
                "name": "Harmony & Backing",
                "presets": [
                    {
                        "name": "Airy Harmonies",
                        "master_volume": 0.78,
                        "chain": [
                            high_pass_filter(100.0),
                            de_esser(0.5, 0.3),
                            compressor(0.2, 4.0, 0.6),
                            eq(0.4, 0.5, 0.65),
                            stereo_widener(0.5, 0.35),
                            reverb(0.45, 0.25, "hall"),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Doubler Effect",
                        "master_volume": 0.8,
                        "chain": [
                            high_pass_filter(90.0),
                            compressor(0.25, 4.0, 0.65),
                            eq(0.45, 0.5, 0.55),
                            chorus(0.2, 0.3, 0.35),
                            delay(220, 0.05, 0.25),
                            reverb(0.3, 0.18, "room"),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "Wide Backing Stack",
                        "master_volume": 0.76,
                        "chain": [
                            high_pass_filter(80.0),
                            de_esser(0.45, 0.35),
                            compressor(0.2, 4.5, 0.55),
                            eq(0.4, 0.55, 0.6),
                            stereo_widener(0.7, 0.4),
                            reverb(0.5, 0.28, "hall"),
                            volume(0.78),
                        ],
                    },
                    {
                        "name": "Soft Pad Vox",
                        "master_volume": 0.74,
                        "chain": [
                            high_pass_filter(120.0),
                            compressor(0.2, 5.0, 0.5),
                            eq(0.4, 0.5, 0.6),
                            chorus(0.18, 0.25, 0.4),
                            shimmer_reverb(0.5, 0.35),
                            volume(0.76),
                        ],
                    },
                ],
            },
            {
                "name": "Vocal FX",
                "presets": [
                    {
                        "name": "Slap Delay",
                        "master_volume": 0.82,
                        "chain": [
                            high_pass_filter(80.0),
                            de_esser(0.5, 0.3),
                            compressor(0.25, 4.0, 0.7),
                            eq(0.45, 0.5, 0.55),
                            delay(120, 0.15, 0.35),
                            reverb(0.25, 0.12, "room"),
                            volume(0.84),
                        ],
                    },
                    {
                        "name": "Ping Pong Echo",
                        "master_volume": 0.8,
                        "chain": [
                            high_pass_filter(80.0),
                            de_esser(0.5, 0.3),
                            compressor(0.25, 4.0, 0.65),
                            eq(0.45, 0.5, 0.55),
                            delay(380, 0.35, 0.3),
                            reverb(0.3, 0.15, "hall"),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "Shimmer Wash",
                        "master_volume": 0.78,
                        "chain": [
                            high_pass_filter(100.0),
                            de_esser(0.55, 0.25),
                            compressor(0.2, 4.0, 0.6),
                            eq(0.4, 0.5, 0.6),
                            shimmer_reverb(0.65, 0.35),
                            delay(500, 0.25, 0.2),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Radio Filter",
                        "master_volume": 0.76,
                        "chain": [
                            high_pass_filter(300.0),
                            low_pass_filter(3500.0),
                            compressor(0.3, 6.0, 0.65),
                            eq(0.3, 0.1, 0.2),
                            reverb(0.2, 0.08, "room"),
                            volume(0.78),
                        ],
                    },
                ],
            },
        ],
    },
    {
        "slug": "backing_tracks",
        "label": "Backing Tracks",
        "bank_start": 27,
        "banks": [
            {
                "name": "Mix Ready",
                "presets": [
                    {
                        "name": "Stereo Master Bus",
                        "master_volume": 0.82,
                        "chain": [
                            high_pass_filter(30.0),
                            low_pass_filter(18000.0),
                            compressor(0.2, 4.0, 0.6),
                            eq(0.5, 0.5, 0.5),
                            stereo_widener(0.3, 0.25),
                            volume(0.85),
                        ],
                    },
                    {
                        "name": "Kick & Bass Focus",
                        "master_volume": 0.8,
                        "chain": [
                            high_pass_filter(25.0),
                            compressor(0.25, 5.0, 0.55),
                            eq(0.65, 0.35, 0.45),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "Full Mix Compressed",
                        "master_volume": 0.78,
                        "chain": [
                            high_pass_filter(30.0),
                            compressor(0.15, 6.0, 0.5),
                            eq(0.5, 0.5, 0.55),
                            multi_tap_delay(200, 0.08, 0.1, 2),
                            reverb(0.15, 0.08, "room"),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Transparent Mix",
                        "master_volume": 0.85,
                        "chain": [
                            high_pass_filter(25.0),
                            compressor(0.2, 3.5, 0.65),
                            eq(0.5, 0.5, 0.5),
                            stereo_widener(0.2, 0.15),
                            volume(0.88),
                        ],
                    },
                ],
            },
            {
                "name": "Click & Guide",
                "presets": [
                    {
                        "name": "Click Track + Backing",
                        "master_volume": 0.78,
                        "chain": [
                            high_pass_filter(40.0),
                            compressor(0.3, 4.0, 0.55),
                            eq(0.5, 0.4, 0.6),
                            reverb(0.2, 0.08, "room"),
                            volume(0.8),
                        ],
                    },
                    {
                        "name": "Guide Vox Monitor",
                        "master_volume": 0.8,
                        "chain": [
                            high_pass_filter(80.0),
                            de_esser(0.5, 0.3),
                            compressor(0.25, 4.0, 0.65),
                            eq(0.45, 0.5, 0.5),
                            reverb(0.3, 0.15, "room"),
                            volume(0.82),
                        ],
                    },
                    {
                        "name": "Scratch Guitar Mix",
                        "master_volume": 0.76,
                        "chain": [
                            noise_gate(0.008),
                            compressor(0.3, 4.0, 0.6),
                            eq(0.5, 0.45, 0.55),
                            reverb(0.2, 0.1, "room"),
                            volume(0.78),
                        ],
                    },
                    {
                        "name": "Stereo Reference",
                        "master_volume": 0.82,
                        "chain": [
                            high_pass_filter(25.0),
                            low_pass_filter(20000.0),
                            compressor(0.18, 4.5, 0.55),
                            eq(0.5, 0.5, 0.55),
                            stereo_widener(0.4, 0.25),
                            volume(0.84),
                        ],
                    },
                ],
            },
            {
                "name": "Ambient Pads",
                "presets": [
                    {
                        "name": "Wash Pad",
                        "master_volume": 0.74,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.2, 5.0, 0.5),
                            eq(0.4, 0.55, 0.5),
                            chorus(0.15, 0.5, 0.4),
                            stereo_widener(0.6, 0.4),
                            shimmer_reverb(0.6, 0.35),
                            volume(0.76),
                        ],
                    },
                    {
                        "name": "Texture Swell",
                        "master_volume": 0.72,
                        "chain": [
                            noise_gate(0.005),
                            expander(0.1, 3.0),
                            eq(0.4, 0.55, 0.55),
                            auto_pan(0.12, 0.35),
                            reverb(0.65, 0.4, "hall"),
                            volume(0.74),
                        ],
                    },
                    {
                        "name": "Drone Bed",
                        "master_volume": 0.7,
                        "chain": [
                            noise_gate(0.005),
                            low_pass_filter(1000.0),
                            eq(0.55, 0.4, 0.35),
                            chorus(0.12, 0.4, 0.45),
                            reverb(0.7, 0.45, "hall"),
                            volume(0.72),
                        ],
                    },
                    {
                        "name": "Cinematic Swell",
                        "master_volume": 0.76,
                        "chain": [
                            noise_gate(0.005),
                            compressor(0.15, 5.0, 0.5),
                            eq(0.4, 0.5, 0.6),
                            stereo_widener(0.7, 0.35),
                            shimmer_reverb(0.55, 0.4),
                            delay(600, 0.2, 0.15),
                            volume(0.78),
                        ],
                    },
                ],
            },
        ],
    },
]


def generate():
    """Write all factory preset JSON files to presets/factory/<channel>/bank_N/."""
    total_presets = 0
    total_banks = 0

    for channel in CHANNELS:
        ch_dir = os.path.join(FACTORY_DIR, channel["slug"])
        bn = channel["bank_start"]

        for bank_idx, bank_def in enumerate(channel["banks"]):
            bank_num = bn + bank_idx
            bank_dir = os.path.join(ch_dir, f"bank_{bank_num}")
            os.makedirs(bank_dir, exist_ok=True)

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

            # presets
            for prog, preset_data in enumerate(bank_def["presets"]):
                preset_json = {
                    "name": preset_data["name"],
                    "bank": bank_num,
                    "program": prog,
                    "master_volume": preset_data["master_volume"],
                    "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")
                total_presets += 1

            total_banks += 1

        print(f"✅ {channel['label']}: {total_banks} banks so far, {total_presets} presets")

    print(f"\n✅ Generated {total_presets} presets across {total_banks} banks in 3 channels:")
    for channel in CHANNELS:
        print(f"   {channel['label']}: {len(channel['banks'])} banks × {len(channel['banks'][0]['presets'])} presets = {len(channel['banks']) * len(channel['banks'][0]['presets'])} presets")


if __name__ == "__main__":
    # Guard against running from wrong cwd
    if not os.path.isdir(FACTORY_DIR):
        # Try resolving relative to the script location
        script_dir = os.path.dirname(os.path.abspath(__file__))
        FACTORY_DIR_ALT = os.path.join(
            os.path.dirname(os.path.dirname(script_dir)), "presets", "factory"
        )
        if os.path.isdir(FACTORY_DIR_ALT):
            FACTORY_DIR = FACTORY_DIR_ALT
        else:
            print(f"Error: factory directory not found at {FACTORY_DIR} or {FACTORY_DIR_ALT}")
            sys.exit(1)
    generate()
