<script module lang="ts">
	export interface StringFormData {
		filename: string;
		description: string;
		content: string;
	}
</script>

<script lang="ts">
	import { untrack } from "svelte";
	import Button from "$lib/components/ui/Button.svelte";
	import Spinner from "$lib/components/ui/Spinner.svelte";
	import ErrorAlert from "$lib/components/ui/Error.svelte";
	import ArrowUp from "$icon/arrow-up";
	import X from "$icon/x";

	interface Props {
		mode?: "create" | "edit";
		filename?: string;
		description?: string;
		content?: string;
		onsubmit: (data: StringFormData) => Promise<void>;
		oncancel?: () => void;
	}

	let {
		mode = "create",
		filename: initialFilename = "",
		description: initialDescription = "",
		content: initialContent = "",
		onsubmit,
		oncancel
	}: Props = $props();

	// seed once; the props can't change while the form is open.
	let filename = $state(untrack(() => initialFilename));
	let description = $state(untrack(() => initialDescription));
	let content = $state(untrack(() => initialContent));
	let isPublishing = $state(false);
	let error = $state<string | null>(null);

	const lineCount = $derived(content === "" ? 0 : content.split("\n").length);
	const byteCount = $derived(new TextEncoder().encode(content).length);

	const handleSubmit = async (e: SubmitEvent) => {
		e.preventDefault();
		isPublishing = true;
		error = null;
		try {
			await onsubmit({ filename, description, content });
		} catch (err) {
			error = err instanceof Error ? err.message : "Failed to publish string";
		} finally {
			isPublishing = false;
		}
	};
</script>

<div class="rounded border border-border-default bg-background-default">
	<form onsubmit={handleSubmit}>
		<div class="flex flex-col gap-2 p-4">
			<div class="flex flex-col gap-2 md:flex-row">
				<input
					type="text"
					id="filename"
					name="filename"
					placeholder="Filename"
					required
					bind:value={filename}
					disabled={isPublishing}
					class="rounded border border-border-default bg-background-default px-2 py-2 text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50 md:max-w-64"
				/>
				<input
					type="text"
					id="description"
					name="description"
					placeholder="Description ..."
					maxlength={280}
					bind:value={description}
					disabled={isPublishing}
					class="flex-1 rounded border border-border-default bg-background-default px-2 py-2 text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50"
				/>
			</div>

			<textarea
				id="content"
				name="content"
				placeholder="Paste your string here!"
				required
				rows={20}
				spellcheck={false}
				bind:value={content}
				disabled={isPublishing}
				class="w-full resize-y rounded border border-border-default bg-background-default px-2 py-2 font-mono text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50"
			></textarea>
		</div>

		<div class="flex items-center justify-between px-4 py-3">
			<div class="text-sm text-foreground-subtle">
				<span>{lineCount} line{lineCount !== 1 ? "s" : ""}</span>
				<span class="px-1 select-none">·</span>
				<span>{byteCount} byte{byteCount !== 1 ? "s" : ""}</span>
			</div>

			<div class="flex items-center gap-2">
				{#if mode === "edit"}
					<Button
						type="button"
						variant="default"
						icon={X}
						disabled={isPublishing}
						onclick={oncancel}
					>
						Cancel
					</Button>
				{/if}
				<Button
					type="submit"
					variant="primary"
					icon={isPublishing ? Spinner : ArrowUp}
					disabled={isPublishing}
				>
					Publish
				</Button>
			</div>
		</div>

		{#if error}
			<div class="px-4 pb-4">
				<ErrorAlert label={error} />
			</div>
		{/if}
	</form>
</div>
