'use client';
import type { ReactElement } from 'react';
import {
parseRevivalExpression, REVIVAL_EXPRESSION_MAX_DEPTH, REVIVAL_EXPRESSION_MAX_LEAVES,
type RevivalExpression,
} from '@/game/revival-expression-promises';
import { Button } from './ui/button';
import { Input } from './ui/input';
type LeaderChoice = { id: string; name: string };
const newLeaf = (): RevivalExpression => ({ kind: 'forces', counter: 'total', minimum: 1 });
export function revivalExpressionInputError(value: unknown): string | null {
try { parseRevivalExpression(value); return null; }
catch (error) { return error instanceof Error ? error.message : 'Choose a valid ordinary Revival expression.'; }
}
// Numeric drafts remain visible and repairable. Only structural controls use
// this detached placeholder tree; the user's original numbers are retained.
const structuralDraft = (node: RevivalExpression): RevivalExpression => node.kind === 'and' || node.kind === 'or'
? { ...node, terms: node.terms.map(structuralDraft) }
: node.kind === 'forces' ? { ...node, minimum: 1 } : node;
const inputSize = (node: RevivalExpression): { leaves: number; depth: number } => {
if (node.kind !== 'and' && node.kind !== 'or') return { leaves: 1, depth: 0 };
const sizes = node.terms.map(inputSize);
return { leaves: sizes.reduce((sum, child) => sum + child.leaves, 0), depth: 1 + Math.max(0, ...sizes.map(child => child.depth)) };
};
/** Hook-free controlled tree, including invalid numeric drafts. Eligibility
* and the whole-expression answer remain authoritative on the server. */
export function RevivalExpressionFields({ value, leaders, disabled, onChange }: {
value: RevivalExpression;
leaders: readonly LeaderChoice[];
disabled: boolean;
onChange: (expression: RevivalExpression) => void;
}) {
const size = inputSize(value), error = revivalExpressionInputError(value);
const commit = (next: RevivalExpression) => {
if (!disabled && !revivalExpressionInputError(structuralDraft(next))) onChange(next);
};
const render = (node: RevivalExpression, path: string, replace: (next: RevivalExpression) => RevivalExpression,
remove?: () => RevivalExpression): ReactElement => {
const group = node.kind === 'and' || node.kind === 'or';
const id = `truth-revival-expression-${path}`;
const allowed = (next: RevivalExpression) => !disabled && !revivalExpressionInputError(structuralDraft(replace(next)));
const change = (next: RevivalExpression) => commit(replace(next));
const wrap = (kind: 'and' | 'or'): RevivalExpression => ({ kind, terms: [node, newLeaf()] });
return
;
};
return ;
}