<template>
  <el-popover
    v-model:visible="visible"
    class="inline-block"
    trigger="click"
    :show-arrow="false"
    :hide-after="50"
    placement="bottom-start"
    :width="250"
    popper-class="color-picker-popover"
  >
    <div class="relative">
      <div class="color-box">
        <p>选择颜色</p>
        <ul class="flex flex-wrap p-extra-small color-list">
          <li
            v-for="color in defaultColors"
            :key="color"
            class="color-item"
            :class="{ active: customColor === color }"
            :style="{ '--color': color }"
            @click="checkColor(color)"
          ></li>
        </ul>
      </div>
      <div class="color-box">
        <p>自定义颜色</p>
        <ul class="flex flex-wrap p-extra-small color-list">
          <li
            v-for="color in historyColors"
            :key="color"
            class="color-item"
            :class="{ active: customColor === color }"
            :style="{ '--color': color }"
            @click="checkColor(color)"
          ></li>
        </ul>
      </div>
      <div class="custom-color-button" @click="onCustomPicker">选择自定义颜色</div>
      <div class="flex items-center justify-between m-t-base confirm-buttons">
        <el-button size="small" type="primary" @click="onConfirm">确定</el-button>
        <el-button size="small" type="primary" plain @click="toggleVisible(false)">取消</el-button>
      </div>
      <input ref="colorInput" v-model="customColor" class="color-input" type="color" />
    </div>
    <template #reference><slot></slot></template>
  </el-popover>
</template>

<script setup lang="ts" name="ColorPicker">
import { reactive, ref, watch } from 'vue'
import { debounce } from 'lodash-es'
import { ElPopover, ElButton } from 'element-plus'
import { localStorage } from '@/plugins/storage'

const props = defineProps<{
  modelValue: string
}>()

const emits = defineEmits<{ (e: 'update:modelValue', color: string): void }>()

const visible = ref<boolean>(false)

const defaultColors = [
  '#fe7e7d',
  '#feff7e',
  '#81ff81',
  '#01fe7f',
  '#80fffe',
  '#0080ff',
  '#fd7fc3',
  '#ff7ffd',
  '#fe0002',
  '#fffc00',
  '#80fe00',
  '#00ff43',
  '#04fdfd',
  '#007fc1',
  '#7f81b7',
  '#fe02f3',
  '#803f40',
  '#fb823e',
  '#05fc03',
  '#018184',
  '#043e7b',
  '#817eff',
  '#810141',
  '#fb0182',
]

const historyColors = ref<string[]>(localStorage.get('HISTORY_CUSTOM_COLOR') || [])

const customColor = ref<string>(props.modelValue)

watch(props, () => {
  customColor.value = props.modelValue
})

watch(
  customColor,
  debounce(() => {
    if (customColor.value && !defaultColors.concat(historyColors.value).includes(customColor.value)) {
      if (historyColors.value.length >= 16) {
        historyColors.value = [customColor.value].concat(historyColors.value.slice(0, 15))
      } else {
        historyColors.value.unshift(customColor.value)
      }
    }
  }, 50)
)

watch(
  historyColors,
  debounce(() => {
    localStorage.set('HISTORY_CUSTOM_COLOR', [...new Set(historyColors.value.slice(0, 16))])
  }, 50)
)

const checkColor = (color: string) => {
  customColor.value = color
}

const colorInput = ref<HTMLInputElement>()

const onCustomPicker = () => {
  colorInput.value?.click()
}

const toggleVisible = (v: boolean) => {
  visible.value = v
}

const onConfirm = () => {
  toggleVisible(false)
  emits('update:modelValue', customColor.value)
}
</script>

<style scoped lang="scss">
.color-box {
  color: $NormalColor;
  .color-list {
    margin-left: -6px;
    .color-item {
      width: 20px;
      height: 20px;
      background-color: var(--color);
      margin-left: 6px;
      margin-bottom: 9px;
      transition: scale 0.1s linear;
      &:hover {
        transform: scale(1.15);
      }
      &.active {
        outline: 1px dashed red;
      }
    }
  }
}
.custom-color-button {
  color: $NormalColor;
  height: 32px;
  line-height: 32px;
  border-radius: 2px;
  margin: 6px 0;
  background-color: rgba(0, 0, 0, 0.1);
  text-align: center;
  cursor: pointer;
  &:hover {
    background-color: rgba(0, 0, 0, 0.08);
  }
}

.confirm-buttons {
  .el-button {
    width: 100px;
  }
}

.color-input {
  width: 0;
  height: 0;
  border: none;
  outline: none;
  opacity: 0;
  position: absolute;
  right: -30px;
  top: 0;
}
</style>
