<script setup lang="ts">
import type { IconType, ValidateInputBaseT } from '@bagelink/vue'
import { Icon, useDebounceFn, useValidateFieldValue } from '@bagelink/vue'

import { onMounted, watch } from 'vue'

export interface TextInputProps extends ValidateInputBaseT {
	id?: string
	title?: string
	helptext?: string
	name?: string
	placeholder?: string
	modelValue?: string | number
	label?: string
	small?: boolean
	dense?: boolean
	required?: boolean
	pattern?: string
	defaultValue?: string | number
	shrink?: boolean
	disabled?: boolean
	type?: string
	nativeInputAttrs?: { [key: string]: any }
	icon?: IconType
	iconStart?: IconType
	multiline?: boolean
	autoheight?: boolean
	code?: boolean
	rows?: number | string
	autocomplete?: AutoFillField
	autofocus?: boolean
	onFocusout?: (e: FocusEvent) => void
	onFocus?: (e: FocusEvent) => void
}

const props = withDefaults(
	defineProps<TextInputProps>(),
	{
		type: 'text',
		modelValue: '',
	},
)
const emit = defineEmits(['update:modelValue', 'debounce'])
let inputVal = $ref<string | number>()

const input = $ref<HTMLInputElement>()

useValidateFieldValue(
	() => inputVal,
	() => input,
	props.validate,
	props.getFormData
)

const inputRows = $computed(() => {
	let rows = Number(props.rows) || 1
	if (props.autoheight) rows = Math.max(rows, String(inputVal).split('\n').length)
	if (props.multiline || props.code) rows = Math.max(rows, 4)
	return rows
})

const debouncedEmit = useDebounceFn(() => { emit('debounce', inputVal as string) }, 700)

function updateInputVal() {
	if (props.disabled) return
	emit('update:modelValue', inputVal as string)
	debouncedEmit()
}

watch(
	() => props.modelValue,
	(newVal) => {
		if (newVal !== inputVal) inputVal = newVal
	},
	{ immediate: true },
)

const hasFocus = () => document.activeElement === input
const focus = () => input?.focus()
defineExpose({ focus, hasFocus })

onMounted(() => {
	if (props.autofocus) setTimeout(() => input?.focus(), 10)
	if (props.defaultValue && !props.modelValue) inputVal = props.defaultValue
})
</script>

<template>
	<div
		class="bagel-input text-input"
		:class="{
			dense,
			small,
			shrink,
			code,
			textInputIconWrap: icon,
			txtInputIconStart: iconStart,
		}"
		:title="title"
	>
		<label :for="id">
			{{ label }} <span v-if="required && label">*</span>

			<input
				v-if="!multiline && !autoheight && !code && inputRows < 2"
				:id
				ref="input"
				v-model.trim="inputVal"
				:name
				:title
				:autocomplete
				:type
				:rows="1"
				:placeholder="placeholder || label"
				:disabled
				:required
				:pattern
				v-bind="nativeInputAttrs"
				@focusout="onFocusout"
				@focus="onFocus"
				@input="updateInputVal"
			>
			<textarea
				v-else
				:id
				ref="input"
				v-model="inputVal"
				:name
				:title
				:type
				:rows="inputRows"
				:placeholder="placeholder || label"
				:disabled
				:required
				:pattern
				v-bind="nativeInputAttrs"
				@input="updateInputVal"
				@focusout="onFocusout"
			/>
			<p v-if="helptext" class="opacity-7 light">{{ helptext }}</p>
			<Icon
				v-if="iconStart"
				class="iconStart"
				:icon="iconStart"
			/>
			<Icon
				v-if="icon"
				:icon
			/>
		</label>
	</div>
</template>

<style>
.bagel-input.shrink,
.bagel-input.shrink input {
	min-width: unset !important;
	/* width: auto; */
}

.bagel-input label {
	font-size: var(--label-font-size);
}
</style>

<style scoped>
.bagel-input textarea {
	min-height: unset;
	font-size: var(--input-font-size);
}

.bagel-input.text-input textarea {
	resize: none;
}

.code textarea {
	font-family: 'Inconsolata', monospace;
	background: var(--bgl-code-bg) !important;
	color: var(--bgl-light-text) !important;
}
.code textarea::placeholder {
	color: var(--bgl-light-text) !important;
	opacity: 0.3;
}

.bagel-input.small {
	margin-bottom: 0;
	height: 30px;
}

.bagel-input.dense label {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.bagel-input input:disabled {
	background: #f5f5f5;

}

.bagel-input label {
	font-size: var(--label-font-size);
}

.textInputIconWrap .bgl_icon-font {
	color: var(--input-color);
	position: absolute;
    inset-inline-end:calc(var(--input-height) / 3 - 0.25rem);
	margin-top: calc(var(--input-height) / 2 + 0.1rem);
	line-height: 0;
}
.textInputIconWrap input{
	padding-inline-end: calc(var(--input-height) / 3 + 1.5rem);
}

.txtInputIconStart .iconStart {
	color: var(--input-color);
	position: absolute;
    inset-inline-start:calc(var(--input-height) / 3 - 0.25rem);
	margin-top: calc(var(--input-height) / 2 );
	line-height: 0;
}
.txtInputIconStart input, .txtInputIconStart textarea{
	padding-inline-start: calc(var(--input-height) / 3 + 1.5rem);
}

.bagel-input.small textarea {
	height: 30px;
}
</style>
