<script setup>
import { ref, useSlots, computed } from 'vue'
import { isNumber, isFunction } from '../utils/assist'
import InputProcessor from '../utils/inputProcessor'
import useStyle from '../hooks/useStyle'
import useSlotConfig from '../hooks/useSlotConfig'

defineOptions({
  name: 'VInput'
})

const root = ref(null)

const props = defineProps({
  field: {
    type: Object,
    required: true
  }
})

const model = defineModel({
  type: [String, Number]
})

const slots = useSlots()

const slotConfig = useSlotConfig(props.field)

const { style } = useStyle(props)

const fieldInfo = computed(() => {
  let { onBlur, style, slots, type, ...rest } = props.field || {}
  return rest
})

function formatValue(value) {
  const { type, number, precision, min, max, mode } = props.field

  if (value === '' || value === null || value === undefined) return value

  let formatValue = value
  if (!InputProcessor.isValidType(type)) {
    if (!isNumber(precision) && !number && !isNumber(min) && !isNumber(max)) return formatValue

    if (isNumber(precision)) {
      formatValue = InputProcessor.toFixed(formatValue, precision, {
        mode
      })
    }
    if (number || isNumber(min) || isNumber(max)) {
      formatValue = InputProcessor.processInRange(formatValue, {
        convertToNumber: !!number,
        min,
        max
      })
    }
    return formatValue
  } else {
    formatValue = InputProcessor.process(formatValue, {
      type,
      convertToNumber: !!number,
      precision,
      mode
    })

    if (value === '' || value === null || value === undefined) return value

    if (isNumber(min) || isNumber(max)) {
      formatValue = InputProcessor.processInRange(formatValue, {
        convertToNumber: !!number,
        min,
        max
      })
    }
  }
  return formatValue
}

function blurHandle(e) {
  const resultValue = formatValue(model.value)
  model.value = resultValue
  const onBlur = props.field.onBlur
  if (onBlur && isFunction(onBlur)) {
    onBlur(e, resultValue)
  }
}

defineExpose({
  root,
  blur() {
    root.value.blur()
  },
  clear() {
    root.value.clear()
  },
  focus() {
    root.value.focus()
  },
  get input() {
    return root.value.input
  },
  get ref() {
    return root.value.ref
  },
  resizeTextarea() {
    root.value.resizeTextarea()
  },
  select() {
    root.value.select()
  },
  get textarea() {
    return root.value.textarea
  },
  get textareaStyle() {
    return root.value.textareaStyle
  }
})
</script>

<template>
  <el-input ref="root" v-model.trim="model" v-bind="fieldInfo" :style="style" @blur="blurHandle">
    <template v-if="slotConfig.prefix && slots[slotConfig.prefix]" #prefix>
      <slot :name="slotConfig.prefix"></slot>
    </template>
    <template v-if="slotConfig.suffix && slots[slotConfig.suffix]" #suffix>
      <slot :name="slotConfig.suffix"></slot>
    </template>
    <template v-if="slotConfig.prepend && slots[slotConfig.prepend]" #prepend>
      <slot :name="slotConfig.prepend"></slot>
    </template>
    <template v-if="slotConfig.append && slots[slotConfig.append]" #append>
      <slot :name="slotConfig.append"></slot>
    </template>
  </el-input>
</template>

<style></style>
