import type { ColorInput } from "bun";
import { Show } from "solid-js";

export type ProgressBarProps = {
	/** Progress fraction, 0–1. Clamped to that range. */
	value: number;
	/** Total width of the bar in cells. Default 20. */
	width?: number;
	/** Color of the filled portion. Default `#d77757`. */
	color?: ColorInput;
	/** Color of the unfilled track. Default `#444`. */
	trackColor?: ColorInput;
	/** Glyph for filled cells. Default `█`. */
	fullChar?: string;
	/** Glyph for empty cells. Default `░`. */
	emptyChar?: string;
	/** Append a ` 42%` label after the bar. Default false. */
	showPercent?: boolean;
};

/**
 * A determinate progress bar: a filled run of `fullChar` over a track of
 * `emptyChar`, sized to `width` cells. `value` is a 0–1 fraction (clamped).
 *
 * ```tsx
 * <ProgressBar value={done() / total} width={30} showPercent />
 * ```
 *
 * `value` is a plain reactive prop, so animating it (e.g. from a signal) repaints
 * the bar each frame. For an indeterminate "busy" state, use `<Spinner>` instead.
 */
export function ProgressBar(props: ProgressBarProps) {
	const width = () => props.width ?? 20;
	const value = () => Math.max(0, Math.min(1, props.value));
	const filled = () => Math.round(value() * width());

	return (
		<box flexDirection="row">
			<text color={props.color ?? "#d77757"}>
				{(props.fullChar ?? "█").repeat(filled())}
			</text>
			<text color={props.trackColor ?? "#444"}>
				{(props.emptyChar ?? "░").repeat(width() - filled())}
			</text>
			<Show when={props.showPercent}>
				<text dim>{` ${Math.round(value() * 100)}%`}</text>
			</Show>
		</box>
	);
}
