<template>
  <div
    :class="[
      cn.b(),
      cn.m(size),
      cn.is('focused', focused),
      cn.is('disabled', disabled),
    ]"
  >
    <label :class="cn.e('wrapper')">
      <Component
        :is="searchIcon"
        :class="cn.e('icon')"
      />

      <input
        ref="inputRef"
        v-model="value"
        type="search"
        :class="cn.e('input')"
        :placeholder="label"
        :disabled="disabled"
        @focus="focused = true"
        @blur="focused = false"
      >

      <UiButton
        v-show="value.length > 0"
        size="small"
        type="link"
        color="secondary"
        :class="cn.e('clear')"
        :icon="clearIcon"
        @click="value = ''"
        @mousedown.prevent
      />
    </label>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { debounce } from 'lodash-es'
import useClassname from '../../composables/use-classname'
import UiButton from '../button/index.vue'

export interface Props {
  label?: string
  size?: 'small' | 'medium' | 'large'
  disabled?: false
  modelValue?: string
}

defineOptions({
  name: 'UiSearch',
})

const props = withDefaults(defineProps<Props>(), {
  size: 'medium',
  disabled: false,
  modelValue: '',
})

const emit = defineEmits<{
  'update:modelValue': [term: string]
}>()

const cn = useClassname('ui-search')

const inputRef = ref(null)
const value = ref(props.modelValue)
const focused = ref(false)

const searchIcon = computed(() => {
  return resolveComponent(props.size === 'small' ? 'ui-icon-s-search' : 'ui-icon-search')
})

const clearIcon = computed(() => {
  return props.size === 'small' ? 's-cross' : 'cross'
})

const onInput = debounce(() => {
  emit('update:modelValue', value.value)
}, 300)

watch(
  () => props.modelValue,
  (term) => {
    value.value = term
  },
)

watch(value, onInput)

function focus() {
  inputRef.value?.focus()
}

defineExpose({
  focus,
})
</script>

<style lang="scss">
@use 'styles';
</style>
