import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from "react";
import { Text, Box } from "ink";
import { useTheme } from "../theme/theme.js";
import { useTerminalSize } from "../hooks/useTerminalSize.js";
import { getContextWindow } from "../../core/model-registry.js";
import { PARTIAL_BLOCKS, LIGHT_SHADE } from "../constants/figures.js";
import { useFocusedAnimation, useReducedMotion } from "./AnimationContext.js";
// Model ID → short display name
const MODEL_SHORT_NAMES = {
    "claude-fable-5": "Fable",
    "claude-mythos-5": "Mythos",
    "claude-opus-5": "Opus",
    "claude-sonnet-5": "Sonnet",
    "claude-haiku-4-5": "Haiku",
    "claude-haiku-4-5-20251001": "Haiku",
    "gpt-5.6-sol": "GPT-5.6 Sol",
    "gpt-5.6-terra": "GPT-5.6 Terra",
    "gpt-5.6-luna": "GPT-5.6 Luna",
    "gpt-5.5": "GPT-5.5",
};
function getShortModelName(model) {
    return MODEL_SHORT_NAMES[model] ?? model;
}
export function getFooterContextPercent(model, tokensIn, options) {
    const limit = getContextWindow(model, options);
    if (!limit || tokensIn === 0)
        return 0;
    return Math.round((tokensIn / limit) * 100);
}
function getContextColor(pct, theme) {
    if (pct >= 80)
        return theme.error;
    if (pct >= 50)
        return theme.warning;
    return theme.success;
}
// ── Thinking-level visual treatment ─────────────────────────
//
// Higher tier = warmer / more saturated color. `xhigh` and `max` add a moving
// shimmer so high-power modes read as visibly "on full power" at a glance.
const MAX_COLOR = "#db2777"; // hot pink — the visible "max power" tone
const MAX_SHIMMER_COLOR = "#f472b6"; // brighter pink that rides the shimmer
const PLAN_COLOR = "#a78bfa";
const PLAN_SHIMMER_COLOR = "#ddd6fe";
const SHIMMER_WIDTH = 2;
function getThinkingColor(level, theme) {
    if (!level)
        return theme.textDim;
    if (level === "low")
        return theme.textMuted;
    if (level === "medium")
        return theme.accent;
    if (level === "high")
        return theme.warning;
    return MAX_COLOR; // xhigh / max
}
/**
 * Per-char shimmer for active footer labels. A bright spot rides across
 * the text; chars within `SHIMMER_WIDTH` of the spot render bright/bold, the
 * rest stay in the base color. Subscribes to the global animation tick so
 * the timer only runs while an active label is visible.
 */
const ShimmerLabel = ({ text, color, shimmerColor, active = true }) => {
    const { active: animationActive, tick } = useFocusedAnimation(active);
    const cycle = text.length + SHIMMER_WIDTH * 2;
    const pos = animationActive ? (tick % cycle) - SHIMMER_WIDTH : -SHIMMER_WIDTH;
    return (_jsx(Text, { children: text.split("").map((ch, i) => {
            const isBright = Math.abs(i - pos) <= SHIMMER_WIDTH;
            return (_jsx(Text, { color: isBright ? shimmerColor : color, bold: isBright, children: ch }, i));
        }) }));
};
export function getThinkingFooterLabel(thinkingLevel) {
    return thinkingLevel ? `Thinking ${thinkingLevel}` : "Thinking off";
}
export function getFooterRightLength({ barWidth, contextPct, modelName, planText = "Plan off", thinkingText, renderMarkdown = true, }) {
    return (barWidth +
        1 +
        String(contextPct).length +
        1 +
        3 +
        modelName.length +
        3 +
        planText.length +
        (renderMarkdown ? 0 : 3 + "raw markdown".length) +
        3 +
        thinkingText.length);
}
export function doesFooterFitOnOneLine({ columns, model, tokensIn, contextWindowOptions, cwd, gitBranch, thinkingLevel, planMode = false, statusBelow, renderMarkdown: _renderMarkdown = true, }) {
    if (statusBelow)
        return false;
    const parts = cwd.split("/").filter(Boolean);
    const displayPath = parts.length > 0 ? parts[parts.length - 1] : cwd;
    const contextPct = getFooterContextPercent(model, tokensIn, contextWindowOptions);
    const modelName = getShortModelName(model);
    const thinkingText = getThinkingFooterLabel(thinkingLevel);
    const planText = planMode ? "Plan on" : "Plan off";
    const leftLen = displayPath.length + 2 + (gitBranch ? gitBranch.length + 5 : 0);
    const rightLen = getFooterRightLength({
        barWidth: 8,
        contextPct,
        modelName,
        planText,
        thinkingText,
    });
    return leftLen + rightLen <= columns - 2;
}
export function Footer({ model, tokensIn, contextWindowOptions, cwd, gitBranch, thinkingLevel, planMode = false, exitPending, statusLabel, statusColor, hideCwd, hideGitBranch, statusBelow, renderMarkdown = true, }) {
    const theme = useTheme();
    const { columns } = useTerminalSize();
    // Show only the current directory name
    const parts = cwd.split("/").filter(Boolean);
    const displayPath = parts.length > 0 ? parts[parts.length - 1] : cwd;
    const contextPct = getFooterContextPercent(model, tokensIn, contextWindowOptions);
    const contextColor = getContextColor(contextPct, theme);
    const sep = _jsx(Text, { color: theme.border, children: " \u2502 " });
    const modelName = getShortModelName(model);
    // Context bar with partial block precision
    const barWidth = 8;
    const fillFloat = Math.min((contextPct / 100) * barWidth, barWidth);
    const barChars = [];
    for (let i = 0; i < barWidth; i++) {
        const cellFill = Math.max(0, Math.min(1, fillFloat - i));
        const eighths = Math.round(cellFill * 8);
        if (eighths === 8) {
            barChars.push(_jsx(Text, { color: contextColor, children: PARTIAL_BLOCKS[8] }, i));
        }
        else if (eighths > 0) {
            barChars.push(_jsx(Text, { color: contextColor, children: PARTIAL_BLOCKS[eighths] }, i));
        }
        else {
            barChars.push(_jsx(Text, { color: theme.textDim, children: LIGHT_SHADE }, i));
        }
    }
    // Thinking labels. Show the actual thinking tier when on (`Thinking xhigh`) so users see what they're
    // paying for. Off is the only state that stays generic.
    const thinkingText = getThinkingFooterLabel(thinkingLevel);
    const planText = planMode ? "Plan on" : "Plan off";
    const thinkingColor = getThinkingColor(thinkingLevel, theme);
    const reducedMotion = useReducedMotion();
    const shimmerMaxPower = (thinkingLevel === "xhigh" || thinkingLevel === "max") && !reducedMotion;
    const shimmerPlan = planMode && !reducedMotion;
    // Calculate whether everything fits on one line
    const rightLen = getFooterRightLength({
        barWidth,
        contextPct,
        modelName,
        planText,
        thinkingText,
        renderMarkdown,
    });
    const availableWidth = columns - 2;
    const fitsOnOneLine = doesFooterFitOnOneLine({
        columns,
        model,
        tokensIn,
        contextWindowOptions,
        cwd,
        gitBranch,
        thinkingLevel,
        planMode,
        statusBelow,
        renderMarkdown,
    });
    const maxPath = fitsOnOneLine ? availableWidth - rightLen - 2 : availableWidth;
    const truncPath = displayPath.length > maxPath && maxPath > 10
        ? "\u2026" + displayPath.slice(displayPath.length - maxPath + 1)
        : displayPath;
    // Shared right-side content
    const rightContent = (_jsxs(_Fragment, { children: [_jsx(Text, { children: barChars }), _jsxs(Text, { color: contextColor, children: [" ", contextPct, "%"] }), sep, _jsx(Text, { color: theme.primary, bold: true, children: modelName }), sep, shimmerPlan ? (_jsx(ShimmerLabel, { text: planText, color: PLAN_COLOR, shimmerColor: PLAN_SHIMMER_COLOR, active: !exitPending })) : (_jsx(Text, { color: planMode ? PLAN_COLOR : theme.textDim, bold: planMode, children: planText })), !renderMarkdown && (_jsxs(_Fragment, { children: [sep, _jsx(Text, { color: theme.warning, bold: true, children: "raw markdown" })] })), sep, shimmerMaxPower ? (_jsx(ShimmerLabel, { text: thinkingText, color: MAX_COLOR, shimmerColor: MAX_SHIMMER_COLOR, active: !exitPending })) : (_jsx(Text, { color: thinkingColor, bold: thinkingLevel === "high", children: thinkingText }))] }));
    if (exitPending) {
        return (_jsx(Box, { paddingLeft: 1, paddingRight: 1, width: columns, children: _jsx(Text, { color: theme.warning, children: "Press Ctrl+C again to exit" }) }));
    }
    const showCwd = !hideCwd;
    const showGitBranch = !hideGitBranch && !!gitBranch;
    // When statusBelow is set, the status renders on its own line under
    // the right content — it's NOT part of the left-chunk layout.
    const showStatusInLeft = !!statusLabel && !statusBelow;
    // First-rendered left chunk: track if we've started the line with the cwd
    // so we know when to insert separators.
    const leftHasContent = showCwd || showGitBranch || showStatusInLeft;
    // Sep helper that only renders if there's already content before it.
    let leftStarted = false;
    const renderLeftSep = (key) => {
        if (!leftStarted) {
            leftStarted = true;
            return null;
        }
        return _jsx(React.Fragment, { children: sep }, key);
    };
    // statusBelow forces the two-line layout (status sits on its own row
    // under model + tokens). The left-chunk render still respects fits-on-one-
    // line for whatever non-status content remains (cwd, git branch).
    if (fitsOnOneLine && !statusBelow) {
        return (_jsxs(Box, { paddingLeft: 1, paddingRight: 1, width: columns, children: [_jsxs(Box, { flexGrow: 1, children: [showCwd && (_jsxs(_Fragment, { children: [renderLeftSep("sep-cwd"), _jsx(Text, { color: theme.textDim, children: truncPath })] })), showGitBranch && (_jsxs(_Fragment, { children: [renderLeftSep("sep-git"), _jsxs(Text, { color: theme.secondary, children: ["\u2387 ", gitBranch] })] })), showStatusInLeft && (_jsxs(_Fragment, { children: [renderLeftSep("sep-status"), _jsx(Text, { color: statusColor ?? theme.text, children: statusLabel })] }))] }), _jsx(Box, { flexShrink: 0, children: rightContent })] }));
    }
    // statusBelow layout: model + tokens row, then status row underneath.
    // The left-chunk content (cwd / git) merges into the model row's left side
    // when present; for gg-editor (hideCwd + hideGitBranch) only the status
    // line is added.
    if (statusBelow) {
        return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, width: columns, children: [_jsxs(Box, { children: [_jsxs(Box, { flexGrow: 1, children: [showCwd && _jsx(Text, { color: theme.textDim, children: truncPath }), showGitBranch && (_jsxs(_Fragment, { children: [showCwd ? sep : null, _jsxs(Text, { color: theme.secondary, children: ["\u2387 ", gitBranch] })] }))] }), _jsx(Box, { flexShrink: 0, children: rightContent })] }), statusLabel && (_jsx(Box, { children: _jsx(Text, { color: statusColor ?? theme.text, wrap: "truncate", children: statusLabel }) }))] }));
    }
    // Two-line layout
    return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, width: columns, children: [leftHasContent && (_jsxs(Box, { children: [showCwd && (_jsx(Text, { color: theme.textDim, wrap: "truncate", children: truncPath })), showGitBranch && (_jsxs(_Fragment, { children: [showCwd ? sep : null, _jsxs(Text, { color: theme.secondary, wrap: "truncate", children: ["\u2387 ", gitBranch] })] })), statusLabel && (_jsxs(_Fragment, { children: [showCwd || showGitBranch ? sep : null, _jsx(Text, { color: statusColor ?? theme.text, wrap: "truncate", children: statusLabel })] }))] })), _jsx(Box, { children: rightContent })] }));
}
//# sourceMappingURL=Footer.js.map