<script lang="ts">
	import type { KeyboardEventHandler } from "svelte/elements";
	import Eye from "$icon/eye";
	import Pencil from "$icon/pencil";
	import Button from "./Button.svelte";
	import ButtonGroup, { segmentProps } from "./ButtonGroup.svelte";
	import Textarea, { textareaMinHeight } from "./Textarea.svelte";
	import { renderMarkup, type MarkupContext } from "$lib/markup";

	interface Props {
		value?: string;
		markup: MarkupContext;
		tab?: "write" | "preview";
		id?: string;
		name?: string;
		rows?: number;
		placeholder?: string;
		disabled?: boolean;
		autofocus?: boolean;
		// drop the textarea/preview background so the editor blends into its surroundings
		transparent?: boolean;
	}

	let {
		value = $bindable(""),
		markup,
		tab = $bindable("write"),
		id,
		name,
		rows = 12,
		placeholder,
		disabled = false,
		autofocus = false,
		transparent = false
	}: Props = $props();

	const surface = $derived(transparent ? "bg-transparent" : "bg-background-default");
	// the preview pane replaces the field in place, so it has to carry the field's own
	// height and inset — otherwise the whole editor resizes every time you switch tabs.
	const pane = `rounded border border-border-default px-2.5 py-2 ${textareaMinHeight}`;

	let preview = $state<Promise<string> | null>(null);
	let textareaEl = $state<HTMLTextAreaElement>();

	// focus on mount (and when returning to the write tab) if requested
	$effect(() => {
		if (autofocus) textareaEl?.focus();
	});

	$effect(() => {
		if (tab !== "preview") {
			preview = null;
			return;
		}
		const source = value;
		if (!source.trim()) {
			preview = null;
			return;
		}
		preview = renderMarkup(source, markup).then((html) => html ?? "");
	});
	// ctrl/cmd+enter submits the enclosing form, mirroring the old htmx editor
	const handleKeydown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
		if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
			e.preventDefault();
			e.currentTarget.form?.requestSubmit();
		}
	};
</script>

<div class="flex flex-col gap-1.5">
	<ButtonGroup class="self-start">
		<Button
			type="button"
			size="sm"
			icon={Pencil}
			{...segmentProps(tab === "write")}
			onclick={() => (tab = "write")}
		>
			Write
		</Button>
		<Button
			type="button"
			size="sm"
			icon={Eye}
			{...segmentProps(tab === "preview")}
			onclick={() => (tab = "preview")}
		>
			Preview
		</Button>
	</ButtonGroup>

	{#if tab === "write"}
		<Textarea
			{id}
			{name}
			{rows}
			resizeable
			{placeholder}
			bind:value
			bind:element={textareaEl}
			{disabled}
			onkeydown={handleKeydown}
			class={transparent ? "bg-transparent" : undefined}
		/>
	{:else}
		{#await preview}
			<div class={`${pane} ${surface} typography-paragraph-small text-foreground-subtle italic`}>Rendering…</div>
		{:then html}
			{#if html}
				<div class={`markup ${pane} ${surface}`}>
					<!-- eslint-disable-next-line svelte/no-at-html-tags -- sanitised in $lib/markup -->
					{@html html}
				</div>
			{:else}
				<div class={`${pane} ${surface} typography-paragraph-small text-foreground-subtle italic`}>
					Nothing to preview.
				</div>
			{/if}
		{:catch}
			<div class={`${pane} ${surface} typography-paragraph-small text-foreground-subtle italic`}>
				Could not render preview.
			</div>
		{/await}
	{/if}
</div>
