<script setup>
import { ref, computed, watch, inject } from "vue"
import MenuItem from "./MenuItem.vue"
import ToggleBar from "./ToggleBar.vue"
import { COMP_NAME } from "./constant"
import { isNumber, isUndefined, deepCopy } from "../utils/assist"
import validate from "../utils/validate"

defineOptions({
  name: COMP_NAME,
  inheritAttrs: false,
})

const props = defineProps({
  width: {
    type: [String, Number],
    default: "auto",
  },
  options: {
    type: Array,
    required: true,
  },
  keyField: {
    type: String,
    default: "key",
  },
  titleField: {
    type: String,
    default: "title",
  },
  childrenField: {
    type: String,
    default: "children",
  },
  showBar: {
    type: Boolean,
    default: false,
  },
  collapse: {
    type: Boolean,
    default: false,
  },
})

const emits = defineEmits(["barClick"])

const rootRef = ref()

const CONFIG = inject("CONFIG_V_MENU")

const transformOptions = (item, level = 0) => {
  if (props.keyField !== "key" && !isUndefined(item[props.keyField])) {
    item.key = item[props.keyField]
    delete item[props.keyField]
  }
  if (props.titleField !== "title" && !isUndefined(item[props.titleField])) {
    item.title = item[props.titleField]
    delete item[props.titleField]
  }
  if (props.childrenField !== "children" && !isUndefined(item[props.childrenField])) {
    item.children = item[props.childrenField]
    delete item[props.childrenField]
  }
  item.level = level
  if (item.children && item.children.length) {
    level++
    item.children.forEach((subItem) => {
      transformOptions(subItem, level)
    })
  }
}

const visibleOptions = computed(() => {
  let filterOptions = deepCopy(props.options.filter((item) => item.hidden !== true))
  filterOptions.forEach((item) => transformOptions(item))
  return filterOptions
})
const widthC = computed(() => {
  let result = props.width
  if (isNumber(result)) {
    result = props.width.toString()
  }
  return validate.isNumber(result) ? result + "px" : result
})

const collapseMerged = ref(props.collapse)

watch(
  () => props.collapse,
  (value) => {
    collapseMerged.value = value
  }
)

const barClick = (value) => {
  emits("barClick", value)
}

defineExpose({
  root: rootRef,
})
</script>

<template>
  <div class="v-menu" :class="collapseMerged ? 'v-menu-collapse' : ''">
    <el-menu ref="rootRef" v-bind="$attrs" :collapse="collapseMerged">
      <MenuItem v-for="(item, index) in visibleOptions" :key="index" :item="item">
      </MenuItem>
    </el-menu>
    <ToggleBar v-if="props.showBar" v-model="collapseMerged" @barClick="barClick"></ToggleBar>
  </div>
</template>

<style>
.v-menu:not(.v-menu-collapse) {
  width: v-bind(widthC);
}

.v-menu .el-menu--vertical:not(.el-menu--collapse) {
  width: v-bind(widthC);
}

.v-menu {
  position: relative;
  transition: all var(--el-transition-duration);
}

.v-menu.v-menu-collapse {
  width: calc(var(--el-menu-icon-width) + var(--el-menu-base-level-padding) * 2);
}

.v-menu>.el-menu {
  border-right: 1px solid var(--v-border-color);
}

.v-menu .v-menu-icon.el-icon {
  color: var(--v-text-color) !important;
}

.v-menu .v-menu-icon:not(.el-icon) {
  margin-right: 5px;
  width: var(--el-menu-icon-width);
}

.v-menu .el-menu-item-group__title {
  font-size: var(--el-menu-item-font-size);
}
</style>
