# config.py
# Persistent hardware configuration. Stored alongside calibration in
# ~/.config/ac/config.json
import json
import os

DEFAULT_CONFIG_PATH = os.path.expanduser("~/.config/ac/config.json")

# Exact mathematical 0 dBu = sqrt(0.001 * 600) = 0.77459667 Vrms
# Convention value used on most datasheets: 0.775 Vrms
# Some broadcast gear uses 0.7752 Vrms
DBU_REF_EXACT = 0.77459667

SESSION_BASE = os.path.expanduser("~/.local/share/ac/sessions")


def session_dir(name):
    return os.path.join(SESSION_BASE, name)


DEFAULTS = {
    "device":         0,
    "output_channel": 0,
    "input_channel":  0,
    "output_port":    None,   # sticky JACK port name, e.g. "Fireface400 (123):AN1"
    "input_port":     None,
    "reference_channel": None,  # capture port index for H1 transfer function reference
    "reference_port":    None,  # sticky JACK port name for reference
    "dbu_ref_vrms":   DBU_REF_EXACT,
    "dmm_host":       None,
    "range_start_hz": 20.0,
    "range_stop_hz":  20000.0,
    "server_enabled": False,
    "gpio_port":      None,
    "session":        None,
    "backend":        None,   # None = auto-detect (JACK first, then sounddevice)
}


def load(path=None):
    path = path or DEFAULT_CONFIG_PATH
    try:
        with open(path) as f:
            data = json.load(f)
        # merge with defaults so new keys always exist
        return {**DEFAULTS, **data}
    except (FileNotFoundError, json.JSONDecodeError):
        return dict(DEFAULTS)


def save(cfg, path=None):
    path = path or DEFAULT_CONFIG_PATH
    os.makedirs(os.path.dirname(path), exist_ok=True)
    # merge with existing so partial updates work
    existing = load(path)
    existing.update(cfg)
    with open(path, "w") as f:
        json.dump(existing, f, indent=2)
    return existing


def show(cfg):
    ref = cfg.get("dbu_ref_vrms", DBU_REF_EXACT)
    print(f"\n  -- Hardware config --")
    print(f"  Device:         {cfg['device']}")
    print(f"  Output channel: {cfg['output_channel']}"
          + (f"  ->  {cfg['output_port']}" if cfg.get("output_port") else ""))
    print(f"  Input channel:  {cfg['input_channel']}"
          + (f"  ->  {cfg['input_port']}" if cfg.get("input_port") else ""))
    ref_ch = cfg.get("reference_channel")
    if ref_ch is not None:
        print(f"  Reference ch:   {ref_ch}"
              + (f"  ->  {cfg['reference_port']}" if cfg.get("reference_port") else ""))
    print(f"  dBu reference: {ref*1000:.4f} mVrms  ({ref:.8f} V)")
    dmm = cfg.get("dmm_host")
    print(f"  DMM host:      {dmm if dmm else '(not configured)'}")
    print(f"  Range:         {cfg.get('range_start_hz', 20):.0f} – {cfg.get('range_stop_hz', 20000):.0f} Hz")
    print()
