//! Catalog of known tmux options (tmux 3.x). Unknown keys remain editable as custom options.

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OptionScope {
    Server,
    Session,
    Window,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueKind {
    Bool,
    Integer,
    Text,
    Key,
    Style,
    Enum,
}

#[derive(Debug, Clone, Copy)]
pub struct OptionDef {
    pub name: &'static str,
    pub scope: OptionScope,
    pub category: &'static str,
    pub kind: ValueKind,
    pub default: &'static str,
    pub description: &'static str,
    pub choices: &'static [&'static str],
}

impl OptionDef {
    pub const fn enum1(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
        choices: &'static [&'static str],
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Enum,
            default,
            description,
            choices,
        }
    }

    pub const fn bool(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Bool,
            default,
            description,
            choices: &[],
        }
    }

    pub const fn text(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Text,
            default,
            description,
            choices: &[],
        }
    }

    pub const fn integer(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Integer,
            default,
            description,
            choices: &[],
        }
    }

    pub const fn key(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Key,
            default,
            description,
            choices: &[],
        }
    }

    pub const fn style(
        name: &'static str,
        scope: OptionScope,
        category: &'static str,
        default: &'static str,
        description: &'static str,
    ) -> Self {
        Self {
            name,
            scope,
            category,
            kind: ValueKind::Style,
            default,
            description,
            choices: &[],
        }
    }
}

pub const ON_OFF: &[&str] = &["on", "off"];
pub const TOP_BOTTOM: &[&str] = &["top", "bottom"];
pub const MODE_KEYS: &[&str] = &["emacs", "vi"];
pub const STATUS_JUSTIFY: &[&str] = &["left", "centre", "center", "right"];
pub const WINDOW_SIZE: &[&str] = &["manual", "largest", "smallest", "latest", "earliest"];
pub const CLIPBOARD: &[&str] = &["on", "external", "off"];
pub const BELL_ACTION: &[&str] = &["none", "any", "current", "other", "all"];
pub const DETACH_ON_DESTROY: &[&str] = &["off", "on", "no-detached", "detached"];

pub static REGISTRY: &[OptionDef] = &[
    // Server
    OptionDef::integer("buffer-limit", OptionScope::Server, "Server", "50", "Max paste buffer slots"),
    OptionDef::integer("command-queue-limit", OptionScope::Server, "Server", "200", "Max queued commands per client"),
    OptionDef::integer("escape-time", OptionScope::Server, "Server", "10", "Milliseconds to wait after Escape"),
    OptionDef::enum1("focus-events", OptionScope::Server, "Server", "off", "Send focus in/out to panes", ON_OFF),
    OptionDef::integer("message-limit", OptionScope::Server, "Server", "100", "Max queued messages"),
    OptionDef::integer("message-line-length", OptionScope::Server, "Server", "1024", "Max message line length"),
    OptionDef::enum1("set-clipboard", OptionScope::Server, "Server", "external", "Clipboard integration", CLIPBOARD),
    OptionDef::text("terminal-features", OptionScope::Server, "Server", "", "Override terminal features list"),
    OptionDef::text("terminal-overrides", OptionScope::Server, "Server", "", "Capability overrides per TERM"),
    // Session — indexing & naming
    OptionDef::integer("base-index", OptionScope::Session, "Session", "0", "First window index"),
    OptionDef::integer("pane-base-index", OptionScope::Window, "Session", "0", "First pane index"),
    OptionDef::enum1("renumber-windows", OptionScope::Session, "Session", "off", "Close gaps in window numbers", ON_OFF),
  OptionDef::key("prefix", OptionScope::Session, "Keys", "C-b", "Primary prefix key"),
    OptionDef::key("prefix2", OptionScope::Session, "Keys", "None", "Secondary prefix key"),
    OptionDef::integer("repeat-time", OptionScope::Session, "Keys", "500", "Repeat last key within N ms"),
    OptionDef::enum1("mode-keys", OptionScope::Session, "Keys", "emacs", "Copy mode key style", MODE_KEYS),
    OptionDef::enum1("status-keys", OptionScope::Session, "Keys", "emacs", "Status/command key style", MODE_KEYS),
    OptionDef::text("key-table", OptionScope::Session, "Keys", "", "Initial key table"),
    OptionDef::text("user-keys", OptionScope::Session, "Keys", "", "User-defined keys"),
    // Mouse & clipboard
    OptionDef::enum1("mouse", OptionScope::Session, "Mouse", "off", "Mouse support", ON_OFF),
    OptionDef::integer("assume-paste-time", OptionScope::Session, "Mouse", "1", "Paste detection threshold (ms)"),
    // History & timing
    OptionDef::integer("history-limit", OptionScope::Session, "Session", "2000", "Scrollback lines per pane"),
    OptionDef::integer("display-time", OptionScope::Session, "Session", "750", "Message display time (ms)"),
    OptionDef::integer("display-panes-time", OptionScope::Session, "Session", "1000", "Display panes indicator time"),
    OptionDef::text("display-panes-colour", OptionScope::Session, "Session", "blue", "Display panes colour"),
    OptionDef::text("display-panes-active-colour", OptionScope::Session, "Session", "red", "Active pane hint colour"),
    // Shell & commands
    OptionDef::text("default-shell", OptionScope::Session, "Session", "", "Shell for new panes"),
    OptionDef::text("default-command", OptionScope::Session, "Session", "", "Command for new panes"),
    OptionDef::text("default-terminal", OptionScope::Session, "Session", "screen", "Default TERM inside tmux"),
    OptionDef::text("default-size", OptionScope::Session, "Session", "80x24", "Default window size"),
    OptionDef::enum1("destroy-unattached", OptionScope::Session, "Session", "off", "Destroy session when last client leaves", ON_OFF),
    OptionDef::enum1("detach-on-destroy", OptionScope::Session, "Session", "on", "Detach clients when session destroyed", DETACH_ON_DESTROY),
    // Titles
    OptionDef::enum1("set-titles", OptionScope::Session, "Session", "off", "Set terminal window title", ON_OFF),
    OptionDef::text("set-titles-string", OptionScope::Session, "Session", "#{session_name}", "Title format string"),
    // Lock
    OptionDef::integer("lock-after-time", OptionScope::Session, "Session", "0", "Lock after N seconds idle (0=off)"),
    OptionDef::text("lock-command", OptionScope::Session, "Session", "lock -np", "Command to lock terminal"),
    // Status line
    OptionDef::enum1("status", OptionScope::Session, "Status", "on", "Show status line", ON_OFF),
    OptionDef::enum1("status-position", OptionScope::Session, "Status", "bottom", "Status line position", TOP_BOTTOM),
    OptionDef::integer("status-interval", OptionScope::Session, "Status", "15", "Status refresh interval (seconds)"),
    OptionDef::enum1("status-justify", OptionScope::Session, "Status", "centre", "Window list alignment", STATUS_JUSTIFY),
    OptionDef::text("status-left", OptionScope::Session, "Status", "", "Left status segment"),
    OptionDef::integer("status-left-length", OptionScope::Session, "Status", "10", "Max length of status-left"),
    OptionDef::text("status-right", OptionScope::Session, "Status", "", "Right status segment"),
    OptionDef::integer("status-right-length", OptionScope::Session, "Status", "10", "Max length of status-right"),
    OptionDef::style("status-style", OptionScope::Session, "Status", "default", "Status line style"),
    OptionDef::text("status-format", OptionScope::Session, "Status", "", "Status line format (two lines)"),
    OptionDef::style("message-style", OptionScope::Session, "Status", "default", "Message line style"),
    OptionDef::style("message-command-style", OptionScope::Session, "Status", "default", "Command prompt style"),
    OptionDef::style("menu-style", OptionScope::Session, "Status", "default", "Menu style"),
    OptionDef::enum1("menu-exit", OptionScope::Session, "Status", "focused", "Exit menu on outside click", &["focused", "cancelled", "off"]),
    // Visual alerts
    OptionDef::enum1("visual-activity", OptionScope::Session, "Alerts", "off", "Highlight on activity", ON_OFF),
    OptionDef::enum1("visual-bell", OptionScope::Session, "Alerts", "off", "Highlight on bell", ON_OFF),
    OptionDef::enum1("visual-silence", OptionScope::Session, "Alerts", "off", "Highlight on silence", ON_OFF),
    OptionDef::enum1("bell-action", OptionScope::Session, "Alerts", "any", "Action on bell", BELL_ACTION),
    OptionDef::enum1("activity-action", OptionScope::Session, "Alerts", "none", "Action on activity", BELL_ACTION),
    OptionDef::enum1("silence-action", OptionScope::Session, "Alerts", "none", "Action on silence", BELL_ACTION),
    OptionDef::text("word-separators", OptionScope::Session, "Session", " !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", "Word boundary characters"),
    OptionDef::text("editor", OptionScope::Session, "Session", "", "Editor for edit-buffer command"),
    OptionDef::text("copy-command", OptionScope::Session, "Session", "", "Command to copy buffer to system"),
    OptionDef::enum1("exit-empty", OptionScope::Server, "Server", "on", "Exit server when no sessions", ON_OFF),
    // Window behaviour
    OptionDef::enum1("aggressive-resize", OptionScope::Window, "Window", "off", "Resize to smallest client", ON_OFF),
    OptionDef::enum1("allow-rename", OptionScope::Window, "Window", "on", "Allow rename-window", ON_OFF),
    OptionDef::enum1("allow-pane-reorder", OptionScope::Window, "Window", "off", "Allow pane drag reorder", ON_OFF),
    OptionDef::enum1("alternate-screen", OptionScope::Window, "Window", "on", "Allow alternate screen", ON_OFF),
    OptionDef::enum1("automatic-rename", OptionScope::Window, "Window", "on", "Rename window to active program", ON_OFF),
    OptionDef::text("automatic-rename-format", OptionScope::Window, "Window", "#{b:pane_current_path}", "Format for automatic rename"),
    OptionDef::enum1("remain-on-exit", OptionScope::Window, "Window", "off", "Keep dead panes open", ON_OFF),
    OptionDef::enum1("synchronize-panes", OptionScope::Window, "Window", "off", "Send input to all panes", ON_OFF),
    OptionDef::enum1("wrap-search", OptionScope::Window, "Window", "on", "Wrap search in copy mode", ON_OFF),
    OptionDef::enum1("window-size", OptionScope::Window, "Window", "latest", "Window size policy", WINDOW_SIZE),
    OptionDef::integer("main-pane-width", OptionScope::Window, "Window", "80", "Main pane width (main-horizontal)"),
    OptionDef::integer("main-pane-height", OptionScope::Window, "Window", "24", "Main pane height (main-vertical)"),
    OptionDef::integer("other-pane-width", OptionScope::Window, "Window", "15", "Other pane width"),
    OptionDef::integer("other-pane-height", OptionScope::Window, "Window", "15", "Other pane height"),
    OptionDef::text("fill-character", OptionScope::Window, "Window", " ", "Padding character"),
    // Monitoring
    OptionDef::enum1("monitor-activity", OptionScope::Window, "Window", "off", "Monitor pane activity", ON_OFF),
    OptionDef::enum1("monitor-bell", OptionScope::Window, "Window", "off", "Monitor bell in window", ON_OFF),
    OptionDef::integer("monitor-silence", OptionScope::Window, "Window", "0", "Monitor silence (seconds, 0=off)"),
    // Clock & modes
    OptionDef::text("clock-mode-colour", OptionScope::Window, "Window", "green", "Clock mode colour"),
    OptionDef::text("clock-mode-style", OptionScope::Window, "Window", "24", "Clock mode: 12 or 24"),
    OptionDef::style("mode-style", OptionScope::Window, "Window", "default", "Copy mode indicator style"),
    // Pane borders & layout
    OptionDef::enum1("pane-border-status", OptionScope::Window, "Panes", "off", "Pane title in border", TOP_BOTTOM),
    OptionDef::text("pane-border-format", OptionScope::Window, "Panes", "", "Pane border format"),
    OptionDef::style("pane-border-style", OptionScope::Window, "Panes", "default", "Inactive pane border"),
    OptionDef::style("pane-border-active-style", OptionScope::Window, "Panes", "default", "Active pane border"),
    OptionDef::text("pane-border-indicators", OptionScope::Window, "Panes", "", "Border indicators (colour, etc.)"),
    OptionDef::text("pane-border-lines", OptionScope::Window, "Panes", "single", "Border line style"),
    OptionDef::style("pane-active-style", OptionScope::Window, "Panes", "default", "Active pane style"),
    OptionDef::style("window-style", OptionScope::Window, "Panes", "default", "Inactive window style"),
    OptionDef::style("window-active-style", OptionScope::Window, "Panes", "default", "Active window style"),
    OptionDef::style("popup-style", OptionScope::Window, "Panes", "default", "Popup style"),
    OptionDef::style("popup-border-style", OptionScope::Window, "Panes", "default", "Popup border style"),
    OptionDef::text("popup-border-lines", OptionScope::Window, "Panes", "single", "Popup border lines"),
    OptionDef::text("pane-colours", OptionScope::Window, "Panes", "", "Eight pane indicator colours"),
    OptionDef::text("pane-title", OptionScope::Window, "Panes", "", "Default pane title format"),
    // Window status formats
    OptionDef::text("window-status-format", OptionScope::Window, "Status formats", "#I:#W", "Inactive window format"),
    OptionDef::text("window-status-current-format", OptionScope::Window, "Status formats", "#I:#W", "Current window format"),
    OptionDef::style("window-status-style", OptionScope::Window, "Status formats", "default", "Inactive window tab style"),
    OptionDef::style("window-status-current-style", OptionScope::Window, "Status formats", "default", "Current window tab style"),
    OptionDef::style("window-status-last-style", OptionScope::Window, "Status formats", "default", "Last active window style"),
    OptionDef::text("window-status-separator", OptionScope::Window, "Status formats", "", "Separator between window segments"),
];

pub const CATEGORIES: &[&str] = &[
    "Server",
    "Session",
    "Keys",
    "Mouse",
    "Status",
    "Status formats",
    "Alerts",
    "Window",
    "Panes",
    "Custom",
];

pub fn find_option(name: &str) -> Option<&'static OptionDef> {
    REGISTRY.iter().find(|d| d.name == name)
}

pub fn scope_flag(scope: OptionScope) -> &'static str {
    match scope {
        OptionScope::Server => "-s",
        OptionScope::Session => "-g",
        OptionScope::Window => "-g",
    }
}

pub fn set_command(scope: OptionScope) -> &'static str {
    match scope {
        OptionScope::Server => "set -s",
        OptionScope::Session => "set -g",
        OptionScope::Window => "setw -g",
    }
}
