<script lang="ts">
	import { Eye, EyeSlash } from 'svelte-heros-v2';
	import type { Snippet } from 'svelte';

	let {
		label,
		notice,
		id,
		name,
		type = 'text',
		value = $bindable(),
		placeholder,
		pattern,
		required = false,
		disabled = false,
		readonly = false,
		checked = $bindable(false),
		size = 'md',
		pickyWidth = true,
		containerClass = '',
		inputElement = $bindable(),
		oninput,
		onclick
	}: {
		label?: Snippet;
		notice?: Snippet;
		id?: string;
		name?: string;
		type?: string;
		value?: string;
		placeholder?: string;
		pattern?: RegExp;
		required?: boolean;
		disabled?: boolean;
		readonly?: boolean;
		checked?: boolean;
		size?: 'xs' | 'sm' | 'md' | 'lg';
		pickyWidth?: boolean;
		containerClass?: string;
		inputElement?: HTMLInputElement;
		oninput?: (e: Event & { currentTarget: EventTarget & HTMLInputElement }) => void;
		onclick?: (e: Event) => void;
	} = $props();

	let initialType = type;

	let passwordEyeSize = {
		xs: '14',
		sm: '18',
		md: '24',
		lg: '30'
	};
</script>

<!-- the cursor-not-allowed class must be set here because a disabled button does not respect the 'cursor' css property -->
<div class={containerClass} class:cursor-not-allowed={type === 'submit' && disabled}>
	{#if type === 'submit'}
		<input
			class="btn"
			class:btn-xs={size === 'xs'}
			class:btn-sm={size === 'sm'}
			class:btn-md={size === 'md'}
			class:btn-lg={size === 'lg'}
			{id}
			type="submit"
			{disabled}
			bind:value
			bind:this={inputElement}
			{oninput}
			{onclick}
		/>
	{:else}
		<div>
			{#if label}
				<label class="label" for={id}>
					<span class="label-text">
						{@render label()}
						{#if required}
							<span class="text-red-700">*</span>
						{/if}
					</span>
				</label>
			{/if}
			<div
				class="relative flex items-center"
				class:sm:max-w-[16rem]={type !== 'checkbox' && pickyWidth}
			>
				<input
					class:checkbox={type === 'checkbox'}
					class:checkbox-xs={type === 'checkbox' && size === 'xs'}
					class:checkbox-sm={type === 'checkbox' && size === 'sm'}
					class:checkbox-md={type === 'checkbox' && size === 'md'}
					class:checkbox-lg={type === 'checkbox' && size === 'lg'}
					class:input,w-full={type !== 'checkbox'}
					class:input-xs={type !== 'checkbox' && size === 'xs'}
					class:input-sm={type !== 'checkbox' && size === 'sm'}
					class:input-md={type !== 'checkbox' && size === 'md'}
					class:input-lg={type !== 'checkbox' && size === 'lg'}
					class:input-bordered={type !== 'checkbox'}
					class:pr-11={initialType === 'password'}
					class:!border-none,!text-inherit={disabled}
					{id}
					{name}
					{type}
					{value}
					{checked}
					{placeholder}
					{required}
					{disabled}
					{readonly}
					bind:this={inputElement}
					autocomplete="off"
					onchange={() => {
						if (type === 'checkbox') {
							checked = !checked;
						}
					}}
					oninput={(e: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
						value = e.currentTarget.value;
						if (pattern && !pattern.test(value)) return;
						oninput?.(e);
					}}
					onpaste={(e) => {
						if (pattern && e.clipboardData && !pattern.test(e.clipboardData.getData('text'))) {
							e.preventDefault();
						}
					}}
					{onclick}
				/>
				{#if initialType === 'password'}
					<button
						class="absolute right-3"
						type="button"
						onclick={() => {
							type = type === 'password' ? 'text' : 'password';
						}}
					>
						{#if type === 'password'}
							<EyeSlash variation="solid" size={passwordEyeSize[size]} />
						{:else}
							<Eye variation="solid" size={passwordEyeSize[size]} />
						{/if}
					</button>
				{/if}
			</div>
			{#if notice}
				<label class="label" for={id}>
					<span class="label-text-alt">
						{@render notice()}
					</span>
				</label>
			{/if}
		</div>
	{/if}
</div>