<template>
  <template v-if="!(elTypeRelation)">
    <template v-if="elType==='el-cascader'">
      <el-cascader
        :id="attr.id"
        v-model="vValue"
        v-bind="Object.assign(props||{}, attr)"
        @blur="emitsHandler('blur')"
        @focus="emitsHandler('focus')"
        @change="emitsHandler('change')"
      />
    </template>
    <template v-else>
      <component
        :id="attr.id"
        :is="elType"
        v-model="vValue"
        v-bind="Object.assign(props||{}, attr)"
        @blur="emitsHandler('blur')"
        @focus="emitsHandler('focus')"
        @change="emitsHandler('change')"
        @select="emitsHandler('change')"
      >
        <template v-if="props?.append" #append>
          {{ props?.append }}
        </template>
        <template v-if="props?.prepend" #prepend>
          {{ props?.prepend }}
        </template>
        <slot></slot>
      </component>
    </template>
  </template>
  <template v-else>
    <component
      :is="elType"
      v-model="vValue"
      v-bind="Object.assign(props||{}, attr)"
      @blur="emitsHandler('blur')"
      @focus="emitsHandler('focus')"
      @change="emitsHandler('change')"
      @select="emitsHandler('change')"
    >
      <template v-for="(child, ci) in options" :key="ci">
        <template v-if="elTypeRelation==='el-option'">
          <component
            :is="elTypeRelation"
            v-bind="Object.assign(child, child?.props || {})"
            :label="child.label"
            :value="child.value"
          >
            {{ child.label }}
          </component>
        </template>
        <template v-else>
          <component
            :is="child.type?`el-${child.type}`:elTypeRelation"
            v-bind="Object.assign(child, child?.props || {})"
            :label="child.value"
          >
            {{ child.label }}
          </component>
        </template>
      </template>
    </component>
  </template>
</template>

<script lang="ts" setup>
import { computed, nextTick, ref, useAttrs, watch } from 'vue'
import { camelToLine } from 'utils'
import { Op } from '../Form/form.type'
import { usePrefix } from '../../../hooks/use-prefix'

const a = ref('')
defineOptions({
  name: 'SDom'
})

interface Props {
  /**
   * 数据绑定值v-model，类型由组件决定
   */
  modelValue: any
  /**
   * 组件类型
   */
  type: string
  /**
   * 组件前缀，默认 el 基于element-plus，使用组件库内部组件时也可以省略
   */
  prefix?: string
  /**
   * 选项数组
   */
  options?: Array<Op>
  /**
   * 对象形式传入组件属性
   */
  props?: any
}

const domProps = withDefaults(defineProps<Props>(), {
  type: '',
  options: () => ([])
})
const attr = useAttrs()
const uPrefix = usePrefix()
const emits = defineEmits<{
  /**
   * 数据绑定事件，v-model
   */
  (e: 'update:modelValue', value: any): void
  /**
   * change事件，数据变化
   */
  (e: 'change', value: any): void
  /**
   * blur事件，失去焦点
   */
  (e: 'blur'): void
  /**
   * blur事件，焦点事件
   */
  (e: 'focus'): void
}>()
const vValue = ref(domProps.modelValue)
const elType = computed(() => `${ uPrefix }-${ domProps.type }`)
const elTypeRelation = computed(() => {
  const relation: any = {
    'select': 'option',
    'checkbox-group': 'checkbox',
    'radio-group': 'radio'
  }
  const type = camelToLine(domProps.type)
  return relation[type] ? `${ uPrefix }-${ camelToLine(relation[type]) }` : ''
})

watch(() => domProps.modelValue, (value) => {
  vValue.value = value
})

async function emitsHandler (type) {
  await nextTick()
  emits(type, vValue.value)
  emits('update:modelValue', vValue.value)
}
</script>
