<script lang="ts">
	import {
		validate,
		type InputValidatorEvent,
		type ValidatorOptions
	} from '@svelte-toolkit/validate';
	import type { HTMLTextareaAttributes } from 'svelte/elements';
	import { generateIdentifier } from './util';
	import { onMount } from 'svelte';
	import Label from './Label.svelte';

	type Props = Omit<HTMLTextareaAttributes, 'id'> & {
		id?: string;
		label?: string;
		invalidMessage?: string | null;
		validate?: ValidatorOptions;
		focus?: boolean;
		compact?: boolean;
		allowResize?: boolean;
		use?: (node: HTMLTextAreaElement) => void;
		ref?: HTMLTextAreaElement | null;
		onvalidate?: (e: InputValidatorEvent) => void;
	};

	let {
		label,
		invalidMessage,
		id = generateIdentifier('textarea-input'),
		name,
		value = $bindable(''),
		placeholder,
		validate: validateOpts,
		disabled = false,
		focus: focusOnMount = false,
		compact = false,
		rows = 4,
		allowResize = false,
		use,
		ref = $bindable<HTMLTextAreaElement | null>(null),
		onvalidate,
		class: classValue,
		...others
	}: Props = $props();

	let valid: boolean = $state(true);

	export const focus = () => {
		if (ref) ref.focus();
	};

	const conditionalUse = $derived(use ? use : () => {});

	onMount(() => {
		if (focusOnMount && ref) {
			ref.focus();
		}
	});
</script>

<div class={['w-full', classValue]}>
	{#if label}
		<Label for={id}>{label}</Label>
	{/if}

	<textarea
		{id}
		{name}
		{placeholder}
		aria-label={placeholder}
		{...others}
		bind:value
		{rows}
		class={[
			'w-full',
			!allowResize && 'resize-none',
			'border-sui-accent w-full rounded-sm border bg-white font-normal transition-colors',
			'text-sui-text placeholder:text-sui-text/60 dark:border-sui-accent/50 dark:bg-sui-text-800 placeholder:font-normal',
			'dark:text-sui-background dark:placeholder:text-sui-background/60 dark:sm:bg-slate-800',
			'ring-sui-primary ring-offset-1 placeholder-shown:text-ellipsis focus:ring-2',
			!compact ? 'px-[1.125rem] py-3.5' : 'px-[0.75rem] py-2',
			!valid && 'border-red-500!',
			disabled &&
				'border-sui-accent/20 text-sui-text/60 dark:text-sui-background/60 cursor-not-allowed'
		]}
		{disabled}
		use:validate={validateOpts}
		use:conditionalUse
		onvalidate={(e) => {
			valid = e.detail.valid;
			onvalidate?.(e);
		}}
		bind:this={ref}
	></textarea>

	{#if validateOpts && invalidMessage !== null}
		<div class={['opacity-0 transition-opacity', !valid && 'opacity-100']}>
			<Label for={id} error>
				{invalidMessage}
			</Label>
		</div>
	{/if}
</div>
