<template>
  <div class="flex items-center p-l-base p-r-base common-mark-header">
    <ul class="flex items-center">
      <li
        v-for="button in usedOperations"
        :key="button.type"
        :ref="(el) => bindRef(button.type, el)"
        class="grid pointer radius-circle fill-light operation-button"
        :title="button.title"
        @click="onOperationClick(button)"
      >
        <svg-icon :name="attrs['icon-' + button.type] as string || 'mark-' + button.type"></svg-icon>
      </li>
    </ul>
    <color-picker v-model="frontColor" :virtual-ref="refs['front-color']" virtual-triggering></color-picker>
    <color-picker v-model="backgroundColor" :virtual-ref="refs['background-color']" virtual-triggering></color-picker>

    <div class="flex flex-1 items-center mark-header">
      <slot></slot>
      <span class="data-item">
        <message :reply-user-id="props.replyUserId" :paper-path="props.paperPath"></message>
      </span>
      <span class="data-item"><user-info></user-info></span>
    </div>
  </div>
</template>

<script setup lang="ts" name="MarkHeader">
import { reactive, ref, computed, useAttrs, watch } from 'vue'
import useFetch from '@/hooks/useFetch'
import SvgIcon from '@/components/common/SvgIcon.vue'
import ColorPicker from '@/components/common/ColorPicker.vue'
import Message from '@/components/shared/message/Message.vue'
import UserInfo from '@/components/shared/UserInfo.vue'

type ButtonType =
  | 'back'
  | 'scale-up'
  | 'scale-down'
  | 'center'
  | 'rotate'
  | 'front-color'
  | 'background-color'
  | 'refresh'
  | 'remark'
  | 'problem'
  | 'example'
  | 'standard'
  | 'delete'
  | 'bookmark'

interface HeaderButton {
  title: string
  type: ButtonType
}

type EventType = Exclude<ButtonType, 'scale-up' | 'scale-down'> | 'scale-change'

const emits = defineEmits<{
  (e: 'click', opt: { type: EventType; value?: number | string | boolean | number[] }): void
  (e: EventType, val: any): void
  (e: 'back'): void
  (e: 'center', val: boolean): void
  (e: 'refresh'): void
  (e: 'remark'): void
  (e: 'problem'): void
  (e: 'example'): void
  (e: 'standard'): void
  (e: 'delete'): void
  (e: 'bookmark'): void
  (e: 'scale-change', val: number): void
  (e: 'rotate', val: number): void
  (e: 'front-color', color: number[]): void
  (e: 'background-color', color: number[]): void
}>()

const buttons: HeaderButton[] = [
  { title: '返回', type: 'back' },
  { title: '放大', type: 'scale-up' },
  { title: '缩小', type: 'scale-down' },
  { title: '居中', type: 'center' },
  { title: '旋转', type: 'rotate' },
  { title: '前景色', type: 'front-color' },
  { title: '背景色', type: 'background-color' },
  { title: '刷新', type: 'refresh' },
  { title: '回评', type: 'remark' },
  { title: '问题卷', type: 'problem' },
  { title: '查看样卷', type: 'example' },
  { title: '评分标准', type: 'standard' },
  { title: '删除当前专家卷', type: 'delete' },
  { title: '设置专家卷', type: 'bookmark' },
]

const props = defineProps<{
  excludeOperations?: ButtonType[]
  includeOperations?: ButtonType[]
  replyUserId?: number | null
  paperPath?: string | null
}>()

const refs = reactive<Partial<Record<ButtonType, Element>>>({
  'front-color': void 0,
  'background-color': void 0,
})

const bindRef = (type: ButtonType, el: any) => {
  if (el) {
    refs[type] = el
  }
}

const usedOperations = computed(() => {
  const viewButtons = props?.includeOperations
    ? buttons.filter((b) => props?.includeOperations?.some((t) => b.type === t))
    : buttons
  return viewButtons.filter((button) => !props.excludeOperations?.some((type) => button.type === type))
})

const attrs = useAttrs()

/** center */
const center = ref<boolean>(false)

/** ratio */
const ratio = ref<number>(1)

/** rotate */
const rotate = ref<number>(0)

/** front-color */
const frontColor = ref<string>('')

/** background-color */
const backgroundColor = ref<string>('')

watch(center, () => emitEvent('center', center.value))

watch(ratio, () => emitEvent('scale-change', ratio.value))

watch(rotate, () => emitEvent('rotate', rotate.value))

watch(frontColor, () => emitEvent('front-color', frontColor.value))

watch(backgroundColor, () => emitEvent('background-color', backgroundColor.value))

const validVal = (val: number, max: number, min: number) => {
  return Math.min(max, Math.max(val, min))
}

const onOperationClick = (button: HeaderButton) => {
  if (['front-color', 'background-color'].includes(button.type)) {
    return
  }
  switch (button.type) {
    case 'scale-up':
      ratio.value = validVal(ratio.value + 0.1, 2, 0.5)
      break
    case 'scale-down':
      ratio.value = validVal(ratio.value - 0.1, 2, 0.5)
      break
    case 'rotate':
      rotate.value = (rotate.value + 90) % 360
      break
    default:
      emitEvent(button.type)
      break
  }
}

const emitEvent = (type: EventType, val?: string | number | boolean | number[]) => {
  if (attrs['on' + type.replace(/^\S/, (s) => s.toUpperCase())]) {
    emits(type, val as any)
  }
  emits('click', { type: type, value: val })
}

type MarkConfig = {
  center: boolean
  ratio: number
  rotate: number
  frontColor: string
  backgroundColor: string
}

const setCurrentConfig = (config: MarkConfig) => {
  center.value = config.center ?? center.value
  ratio.value = config.ratio ?? ratio.value
  rotate.value = config.rotate ?? rotate.value
  frontColor.value = config.frontColor ?? frontColor.value
  backgroundColor.value = config.backgroundColor ?? backgroundColor.value
}

const loadUserConfig = async () => {
  try {
    const configStr = await useFetch('getUserMarkConfig').fetch()
    const config = JSON.parse(configStr)
  } catch (error) {
    console.error(error)
  }
}
</script>

<style scoped lang="scss">
.common-mark-header {
  height: $MainLayoutHeaderHeight;
  background-color: $MainLayoutHeaderBg;
  .operation-button {
    width: 32px;
    height: 32px;
    place-items: center;
    color: $RegularFontColor;
    &:hover {
      background: $color--primary;
      color: $color--white;
    }
  }
  .mark-header {
    margin-left: auto;
    color: $RegularFontColor;
    font-size: $SmallFont;
    ::v-deep(.data-item) {
      padding-left: 20px;
      display: flex;
      align-items: center;
      &:first-child {
        margin-left: auto;
      }
      &:not(:last-child):after {
        content: '';
        margin-left: 20px;
        display: inline-block;
        width: 1px;
        height: 16px;
        vertical-align: middle;
        background-color: #eeeeee;
      }
    }
  }
}
</style>
