<script setup>
import { isUndefined, isString, typeOf, checkTypesCorrect } from '../utils/assist'
import { COMP_NAME, TITLE_TYPES, ICON_TYPES, ICON_SIZE_TYPES, OPTION_TYPE_VALUES } from './constant'
import VMenuIcon from './VMenuIcon.vue'
import VRender from '../VRender/index.vue'

defineOptions({
  name: 'VMenuItem'
})
const props = defineProps({
  item: {
    type: Object,
    required: true,
    validator(v) {
      const { key, title, icon, iconSize, type = 'default' } = v
      if (isUndefined(key)) {
        throw new Error(`${COMP_NAME}:options中需传入唯一标志符key字段`)
      }
      if (!isString(key)) {
        throw new TypeError(`${COMP_NAME}:options中的key字段需设置为String类型`)
      }
      if (isUndefined(title)) {
        throw new Error(`${COMP_NAME}:options中需传入菜单标题title字段`)
      }
      if (!TITLE_TYPES.includes(typeOf(title))) {
        throw new Error(`${COMP_NAME}:options中的title字段需设置为${TITLE_TYPES.join('|')}类型`)
      }

      if (!checkTypesCorrect(icon, ICON_TYPES)) {
        throw new TypeError(`${COMP_NAME}:options中的icon字段需设置为${ICON_TYPES.join('|')}类型`)
      }
      if (!checkTypesCorrect(iconSize, ICON_SIZE_TYPES)) {
        throw new TypeError(
          `${COMP_NAME}:options中的iconSize字段需设置为${ICON_SIZE_TYPES.join('|')}类型`
        )
      }
      if (!OPTION_TYPE_VALUES.includes(type)) {
        throw new TypeError(
          `${COMP_NAME}:options中的type字段需设置为${OPTION_TYPE_VALUES.join('|')}`
        )
      }
      return true
    }
  }
})

const setLevelVar = (level) => {
  return `--el-menu-level: ${level}`
}
</script>

<template>
  <!-- 有子菜单项 -->
  <template v-if="props.item.children && props.item.children.length">
    <el-sub-menu
      v-if="!props.item.type || props.item.type === 'default'"
      :index="props.item.key"
      :popper-class="props.item.popperClass"
      :disabled="props.item.disabled"
      :teleported="props.item.teleported"
      :popper-offset="props.item.popperOffset"
      :expand-close-icon="props.item.expandCloseIcon"
      :expand-open-icon="props.item.expandOpenIcon"
      :collapse-close-icon="props.item.collapseCloseIcon"
      :collapse-open-icon="props.item.collapseOpenIcon"
      :style="setLevelVar(props.item.level)"
      v-bind="$attrs"
    >
      <template #title>
        <VMenuIcon
          class="v-menu-icon"
          v-if="props.item.icon"
          :icon="props.item.icon"
          :size="props.item.iconSize"
          :color="props.item.iconColor"
        ></VMenuIcon>
        <VRender :render="props.item.title"></VRender
      ></template>
      <MenuItem
        v-for="subItem in props.item.children"
        :key="`sub-${subItem.key}`"
        :index="subItem.key"
        :item="subItem"
        :style="setLevelVar(subItem.level)"
        @click="
          (...rest) => {
            subItem.click && subItem.click(...rest)
          }
        "
      ></MenuItem>
    </el-sub-menu>
    <el-menu-item-group v-bind="$attrs" :style="setLevelVar(props.item.level)" v-else>
      <template #title>
        <VMenuIcon
          v-if="props.item.icon"
          :icon="props.item.icon"
          :size="props.item.iconSize"
          :color="props.item.iconColor"
        ></VMenuIcon>
        <VRender :render="props.item.title"></VRender
      ></template>
      <MenuItem
        v-for="subItem in props.item.children"
        :key="`group-sub-${subItem.key}`"
        :index="subItem.key"
        :item="subItem"
        :style="setLevelVar(subItem.level)"
        @click="
          (...rest) => {
            subItem.click && subItem.click(...rest)
          }
        "
      ></MenuItem>
    </el-menu-item-group>
  </template>
  <!-- 无子菜单项 -->
  <el-menu-item
    v-else
    :index="props.item.key"
    :disabled="props.item.disabled"
    v-bind="$attrs"
    :route="props.item.route"
    :style="setLevelVar(props.item.level)"
    @click="
      (...rest) => {
        props.item.click && props.item.click(...rest)
      }
    "
  >
    <VMenuIcon
      class="v-menu-icon"
      v-if="props.item.icon"
      :icon="props.item.icon"
      :size="props.item.iconSize"
      :color="props.item.iconColor"
    ></VMenuIcon>
    <template #title> <VRender :render="props.item.title"></VRender> </template
  ></el-menu-item>
</template>

<style></style>
