import { DynamicBorder } from "../../../../modes/interactive/components/index.js";
import { Container, Spacer } from "@earendil-works/pi-tui";
import { BodyResidualSpacer } from "./body-residual-spacer.js";
import { QuestionTabStrategy, SubmitTabStrategy } from "./tab-content-strategy.js";
export const HINT_PART_ENTER = "enter select";
export const HINT_PART_NAV = "↑/↓ navigate";
export const HINT_PART_TOGGLE = "space toggle";
export const HINT_PART_NOTES = "n add notes";
export const HINT_PART_TAB = "tab switch questions";
export const HINT_PART_CANCEL = "esc cancel";
export const HINT_SINGLE = [HINT_PART_ENTER, HINT_PART_NAV, HINT_PART_CANCEL].join(" · ");
export const HINT_MULTI = [HINT_PART_ENTER, HINT_PART_NAV, HINT_PART_TAB, HINT_PART_CANCEL].join(" · ");
export const HINT_MULTISELECT_SUFFIX = ` · ${HINT_PART_TOGGLE}`;
export const HINT_NOTES_SUFFIX = ` · ${HINT_PART_NOTES}`;
export const REVIEW_HEADING = "Review your answers";
export const READY_PROMPT = "Ready to submit your answers?";
export const INCOMPLETE_WARNING_PREFIX = "⚠ Answer remaining questions before submitting:";
/**
 * The 7th renderable, promoted from a structural literal to a named class so
 * all view-layer components share one explicit `implements StatefulView<P>`
 * contract. `setProps(DialogProps)` writes the live cell read by the
 * strategy thunk during `render()`. `liveProps.activePreviewPane` is a
 * resolved pane reference threaded by the adapter per tick — the dialog
 * itself does not derive it.
 */
export class DialogView {
    constructor(config, initialProps) {
        this.config = config;
        this.liveProps = initialProps;
        this.questionStrategy = new QuestionTabStrategy({
            theme: config.theme,
            questions: config.questions,
            getPreviewPane: () => this.liveProps.activePreviewPane,
            tabsByIndex: config.tabsByIndex,
            notesInput: config.notesInput,
            chatRow: config.chatRow,
            isMulti: config.isMulti,
            getCurrentBodyHeight: config.getCurrentBodyHeight,
        });
        this.submitStrategy = config.isMulti
            ? new SubmitTabStrategy({
                theme: config.theme,
                questions: config.questions,
                submitPicker: config.submitPicker,
            })
            : undefined;
        this.maxFooterRowCount = Math.max(this.questionStrategy.footerRowCount, this.submitStrategy?.footerRowCount ?? 0);
    }
    setProps(props) {
        this.liveProps = props;
    }
    handleInput(_data) { }
    // Invalidation is driven by `QuestionnairePropsAdapter.invalidate()`, which
    // owns the full set of renderables (binding registries + extras like
    // `notesInput`). DialogView has no cached layout of its own.
    invalidate() { }
    render(width) {
        const onSubmit = this.config.isMulti && this.liveProps.state.currentTab === this.config.questions.length;
        const strategy = onSubmit && this.submitStrategy ? this.submitStrategy : this.questionStrategy;
        return this.buildContainerFromStrategy(strategy).render(width);
    }
    buildContainerFromStrategy(strategy) {
        const { theme, isMulti, tabBar } = this.config;
        const state = this.liveProps.state;
        const container = new Container();
        const border = () => new DynamicBorder((s) => theme.fg("accent", s));
        container.addChild(border());
        if (isMulti && tabBar)
            container.addChild(tabBar);
        container.addChild(new Spacer(1));
        for (const c of strategy.headingRows(state))
            container.addChild(c);
        container.addChild(strategy.bodyComponent(state));
        container.addChild(new Spacer(1));
        for (const c of strategy.midRows(state))
            container.addChild(c);
        container.addChild(border());
        for (const c of strategy.footerRows(state))
            container.addChild(c);
        // Residual spacer equalizes total height across strategies; rendered AFTER the bottom border.
        container.addChild(new BodyResidualSpacer((w) => this.config.getBodyHeight(w) + this.maxFooterRowCount, (w) => strategy.bodyHeight(w, state) + strategy.footerRowCount));
        return container;
    }
}
//# sourceMappingURL=dialog-builder.js.map