import type { ColorInput } from "bun";
import type { Accessor, Element as JSXElement } from "solid-js";
import { Animated } from "./animated.tsx";
import { pulse, shimmer, wave } from "./effects.ts";

/**
 * Named wrappers for the built-in effects. Each runs its effect across all of
 * its children as one linked region — so a shimmer (or wave, or pulse) sweeps a
 * spinner glyph and the text beside it together:
 *
 * ```tsx
 * <Shimmer baseColor="#666" highlightColor="#fff">
 *   <Spinner />
 *   <text>{` ${verb}…`}</text>
 * </Shimmer>
 * ```
 *
 * For a custom effect, use `<Animated effect={…}>` directly.
 */

type GroupProps = {
	children: JSXElement;
	/** Freeze the animation at its resting color. */
	paused?: boolean;
	/** Clock tick in ms. Default 50. */
	tick?: number;
	/** Share an external clock instead of creating one. */
	time?: Accessor<number>;
};

export type ShimmerProps = GroupProps & {
	baseColor: ColorInput;
	highlightColor: ColorInput;
	/** Milliseconds per cell. Lower = faster. Default 200. */
	speed?: number;
	/** Sweep direction. Default "ltr". */
	direction?: "ltr" | "rtl";
};

export function Shimmer(props: ShimmerProps) {
	return (
		<Animated
			effect={shimmer({
				baseColor: () => props.baseColor,
				highlightColor: () => props.highlightColor,
				speed: props.speed,
				direction: props.direction,
			})}
			paused={props.paused}
			tick={props.tick}
			time={props.time}
		>
			{props.children}
		</Animated>
	);
}

export type WaveProps = GroupProps & {
	from: ColorInput;
	to: ColorInput;
	/** Milliseconds per full cycle. Default 1500. */
	speed?: number;
	/** Cells per wave. Default 6. */
	wavelength?: number;
};

export function Wave(props: WaveProps) {
	return (
		<Animated
			effect={wave({
				from: () => props.from,
				to: () => props.to,
				speed: props.speed,
				wavelength: props.wavelength,
			})}
			paused={props.paused}
			tick={props.tick}
			time={props.time}
		>
			{props.children}
		</Animated>
	);
}

export type PulseProps = GroupProps & {
	baseColor: ColorInput;
	flashColor: ColorInput;
	/** Full cycle period in ms. Default 2000. */
	period?: number;
};

export function Pulse(props: PulseProps) {
	return (
		<Animated
			effect={pulse({
				baseColor: () => props.baseColor,
				flashColor: () => props.flashColor,
				period: props.period,
			})}
			paused={props.paused}
			tick={props.tick}
			time={props.time}
		>
			{props.children}
		</Animated>
	);
}
