import { Container, getKeybindings, Spacer, Text } from "@earendil-works/pi-tui";
import { formatContextWindow } from "../../../core/context-window.js";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
import { keyHint, rawKeyHint } from "./keybinding-hints.js";
/** Gap (in columns) between the label column and the right-hand token column. */
const TOKEN_COLUMN_GAP = 3;
/**
 * Build the ordered, deduped context-window choices for the picker. The smallest
 * window is the model's native default ("Default"), the largest is "Long context",
 * and any extra tiers fall back to their formatted size. Raw token counts remain the
 * stable identity so colliding display labels never affect selection.
 */
export function buildContextWindowChoices(availableContextWindows, currentContextWindow) {
    const sorted = Array.from(new Set(availableContextWindows)).sort((a, b) => a - b);
    const smallest = sorted[0];
    const largest = sorted[sorted.length - 1];
    const choices = sorted.map((contextWindow) => {
        let label;
        if (contextWindow === smallest) {
            label = "Default";
        }
        else if (contextWindow === largest) {
            label = "Long context";
        }
        else {
            label = formatContextWindow(contextWindow);
        }
        return {
            contextWindow,
            value: String(contextWindow),
            label,
            isDefault: contextWindow === smallest,
            tokensLabel: `${formatContextWindow(contextWindow)} tokens`,
        };
    });
    const currentIndex = sorted.indexOf(currentContextWindow);
    return { choices, currentIndex: currentIndex >= 0 ? currentIndex : 0 };
}
/**
 * Faithful re-creation of the GitHub Copilot CLI context-window picker, surfaced as a
 * follow-up step in the `/model` flow for models that expose more than one window.
 *
 * Renders numbered rows with a `❯` caret, semantic tier labels, a dim `(default)` tag,
 * and right-aligned dim token counts:
 *
 * ```
 * Select Context Window for GPT-5.5
 *
 *    1. Default (default)   400k tokens
 *  ❯ 2. Long context        1m tokens
 *
 *  1-2 select · up/down navigate · enter confirm · esc cancel
 * ```
 */
export class ContextWindowSelectorComponent extends Container {
    constructor(modelName, availableContextWindows, currentContextWindow, onSelect, onCancel) {
        super();
        const { choices, currentIndex } = buildContextWindowChoices(availableContextWindows, currentContextWindow);
        this.choices = choices;
        this.selectedIndex = currentIndex;
        this.onSelectCallback = onSelect;
        this.onCancelCallback = onCancel;
        this.addChild(new DynamicBorder());
        this.addChild(new Spacer(1));
        this.addChild(new Text(theme.fg("accent", `Select Context Window for ${modelName}`), 0, 0));
        this.addChild(new Spacer(1));
        this.listContainer = new Container();
        this.addChild(this.listContainer);
        this.addChild(new Spacer(1));
        this.addChild(new Text(this.getHintBar(), 0, 0));
        this.addChild(new DynamicBorder());
        this.updateList();
    }
    getHintBar() {
        const separator = theme.fg("muted", "  ·  ");
        return [
            rawKeyHint(`1-${this.choices.length}`, "select"),
            rawKeyHint("up/down", "navigate"),
            keyHint("tui.select.confirm", "confirm"),
            keyHint("tui.select.cancel", "cancel"),
        ].join(separator);
    }
    updateList() {
        this.listContainer.clear();
        const numberColumnWidth = `${this.choices.length}.`.length;
        const leftText = (choice, index) => {
            const number = `${index + 1}.`.padStart(numberColumnWidth);
            const defaultTag = choice.isDefault ? " (default)" : "";
            return `${number} ${choice.label}${defaultTag}`;
        };
        const leftColumnWidth = Math.max(...this.choices.map((choice, index) => leftText(choice, index).length));
        this.choices.forEach((choice, index) => {
            const isSelected = index === this.selectedIndex;
            const caret = isSelected ? theme.fg("accent", "❯ ") : "  ";
            const number = theme.fg("muted", `${`${index + 1}.`.padStart(numberColumnWidth)} `);
            const label = isSelected ? theme.fg("accent", choice.label) : choice.label;
            const defaultTag = choice.isDefault ? theme.fg("muted", " (default)") : "";
            const padding = " ".repeat(leftColumnWidth - leftText(choice, index).length + TOKEN_COLUMN_GAP);
            const tokens = theme.fg("muted", choice.tokensLabel);
            this.listContainer.addChild(new Text(`${caret}${number}${label}${defaultTag}${padding}${tokens}`, 0, 0));
        });
    }
    handleInput(keyData) {
        const kb = getKeybindings();
        if (kb.matches(keyData, "tui.select.up") || keyData === "k") {
            this.selectedIndex = this.selectedIndex === 0 ? this.choices.length - 1 : this.selectedIndex - 1;
            this.updateList();
            return;
        }
        if (kb.matches(keyData, "tui.select.down") || keyData === "j") {
            this.selectedIndex = this.selectedIndex === this.choices.length - 1 ? 0 : this.selectedIndex + 1;
            this.updateList();
            return;
        }
        if (kb.matches(keyData, "tui.select.confirm")) {
            this.confirm(this.selectedIndex);
            return;
        }
        if (kb.matches(keyData, "tui.select.cancel")) {
            this.onCancelCallback();
            return;
        }
        // Number shortcuts (1-9) select the matching row directly.
        if (/^[1-9]$/.test(keyData)) {
            this.confirm(Number.parseInt(keyData, 10) - 1);
        }
    }
    confirm(index) {
        const choice = this.choices[index];
        if (choice) {
            this.onSelectCallback(choice.contextWindow);
        }
    }
}
//# sourceMappingURL=context-window-selector.js.map