<template>
  <div class="def-icon-choose">
    <!--选择输入框-->
    <el-select
      ref="selectRef"
      v-model="iconVal"
      :placeholder="$t('component.iconPicker.title')"
      clearable
      :disabled="disabled"
      @click="handleOpen"
      @clear="emits('update:iconName', '')"
    >
      <template #prefix v-if="iconVal">
        <el-icon class="el-input__icon"><def-icon :icon="iconVal" /></el-icon>
      </template>
    </el-select>
    <!--对话框区域-->
    <el-dialog
      v-model="dialogVisible"
      :title="$t('component.iconPicker.title')"
      draggable
      @close="handleClose"
    >
      <!--表单查询-->
      <el-form ref="formRef" class="icon-form" :model="formModel" inline>
        <el-form-item
          :label="$t('component.iconPicker.iconName')"
          prop="formSearchVal"
          size="default"
        >
          <el-input
            v-model="formModel.formSearchVal"
            :placeholder="$t('placeholder.input')"
            clearable
          />
        </el-form-item>
        <el-form-item
          :label="$t('component.iconPicker.iconType')"
          prop="formSelectVal"
          size="default"
        >
          <el-select
            v-model="formModel.formSelectVal"
            :placeholder="$t('placeholder.select')"
          >
            <template v-for="item in formSortList" :key="item.value">
              <el-option :label="item.label" :value="item.value" />
            </template>
          </el-select>
        </el-form-item>
      </el-form>
      <!--图标列表-->
      <el-scrollbar
        ref="scrollbarRef"
        class="icon-scrollbar"
        v-if="iconList.length"
      >
        <ul class="icon-list">
          <template v-for="(icon, index) in iconList" :key="index">
            <li class="icon-list-item" @click="handleIconClick(icon)">
              <def-icon :icon="icon" />
              <span class="icon-name">{{ icon }}</span>
            </li>
          </template>
        </ul>
      </el-scrollbar>
      <el-empty v-else :description="$t('tips.noData')" />
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { useThemeStore } from '@/store/theme'
import { storeToRefs } from 'pinia'
import { $debounce } from '@/utils/def'
import type { FormInstance } from 'element-plus'
import { ElScrollbar, ElSelect } from 'element-plus'
// 加载element图标
import * as ElementPlusIcons from '@element-plus/icons-vue'
// 国际化
import { useI18n } from 'vue-i18n'
// 加载本地svg图标
const LocalIcons = require.context(
  // 组件文件夹的相对路径
  '../../assets/icons/svg',
  // 是否查找子目录
  false,
  // 匹配基础组件文件名的正则表达式
  /\.svg$/
)
const { t } = useI18n()

/* 参数相关 */
const props = defineProps<{
  iconName: string // 图标名
  disabled?: boolean // 是否禁用
}>()
const emits = defineEmits(['update:iconName'])

/* 获取主题色变量 */
const themeStore = useThemeStore()
const { mainColor } = storeToRefs(themeStore)

/* 处理element图标 */
const iconVal = ref<string>(props.iconName)
const dialogVisible = ref<boolean>(false)
const elIconList = ref<string[]>([])
elIconList.value = Object.keys(ElementPlusIcons)

/* 处理本地图标 */
const localIconList = ref<string[]>([])
LocalIcons.keys().forEach((iconName) => {
  iconName = iconName.replace('./', 'svg-').replace('.svg', '')
  localIconList.value.push(iconName)
})

/* 所有图标 */
const allIconList = ref<string[]>([])
allIconList.value = [...elIconList.value, ...localIconList.value]

/* 处理表单 */
const formRef = ref<FormInstance>()
const formModel = reactive({
  formSearchVal: '',
  formSelectVal: 'all'
})
const formSortList = ref([
  /* { label: '全部图标', value: 'all' },
  { label: '本地图标', value: 'local' },
  { label: 'element图标', value: 'element' } */
  { label: t('component.iconPicker.iconTypeObj.all'), value: 'all' },
  { label: t('component.iconPicker.iconTypeObj.local'), value: 'local' },
  { label: t('component.iconPicker.iconTypeObj.element'), value: 'element' }
])
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>()
// 处理当前数据列表
const iconList = ref<string[]>([])
const resetIconList = () => {
  switch (formModel.formSelectVal) {
    case 'all':
      iconList.value = allIconList.value
      break
    case 'element':
      iconList.value = elIconList.value
      break
    case 'local':
      iconList.value = localIconList.value
      break
  }
  scrollbarRef.value?.setScrollTop(0)
}
// 对话框打开
const selectRef = ref<InstanceType<typeof ElSelect>>()
const handleOpen = () => {
  if (props.disabled) return
  selectRef?.value?.blur() // 隐藏select下拉框
  dialogVisible.value = true
  formRef?.value?.resetFields()
  resetIconList()
}
watch(
  () => formModel.formSelectVal,
  () => {
    resetIconList()
  }
)
// 模糊查询
const debounceSearchIcon = $debounce(() => {
  resetIconList()
  iconList.value = iconList.value.filter((item: string) =>
    item.includes(formModel.formSearchVal)
  )
}, 500)
watch(
  () => formModel.formSearchVal,
  () => {
    debounceSearchIcon()
  }
)
// 图标选择
const handleIconClick = (icon: string) => {
  iconVal.value = icon
  emits('update:iconName', icon)
  handleClose()
}
// 对话框关闭
const handleClose = () => {
  dialogVisible.value = false
}

// 清空图标
const clear = () => {
  iconVal.value = ''
  emits('update:iconName', '')
}
defineExpose({
  clear
})
</script>

<style scoped lang="scss">
.def-icon-choose {
  :deep(.el-dialog__body) {
    overflow: hidden;
    padding: 0 20px 20px;
    height: 600px;

    @include flexCol;
  }
  .icon-form {
    @include flexRowEnd;
    .el-form-item {
      &:last-of-type {
        margin-right: 0;
      }
    }
  }
  .icon-scrollbar {
    flex: 1;
    margin-top: 40px;
    .icon-list {
      @include gridAutoCol(120px, 150px);

      grid-auto-rows: 90px;
      .icon-list-item {
        line-height: normal;

        @include flexColCenter;

        border: 0.5px solid #eeeeee;
        &:hover {
          cursor: pointer;
          color: v-bind(mainColor);
          background-color: #f2f6fc;
        }
        .def-icon {
          font-size: 20px;
        }
        .icon-name {
          margin-top: 5px;
          font-size: 14px;
        }
      }
    }
  }
}
</style>
