<template>
  <div class="keyboard-wrapper">
    <el-input ref="inputRef" v-model="model" @focus="focusInput" @keyup.enter="handleEnter" v-bind="$attrs">
      <template v-for="index in slotList" :key="index" #[index]>
        <slot :name="index"></slot>
      </template>
    </el-input>

    <el-popover ref="popoverRef" :visible="visible" :virtual-ref="inputRef" virtual-triggering placement="bottom"
      :width="width" :show-arrow="false" :hide-after="0" popper-style="padding: 0px;color:#000" :persistent="false"
      popper-class="keyboard-popper" @after-enter="afterEnter" @before-leave="beforeLeave">
      <div class="simple-keyboard"></div>
    </el-popover>
  </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted, useSlots } from 'vue'
import Keyboard from 'simple-keyboard'
import 'simple-keyboard/build/css/index.css'
// import layout from 'simple-keyboard-layouts/build/layouts/chinese.js'
defineOptions({
  inheritAttrs: false,
})
const model = defineModel<string>()
const emits = defineEmits(['onChange', 'enter', 'close', 'focus'])

const slots = useSlots();
const slotList = ref<any[]>([]); // 使用泛型指定数组类型
slotList.value = Object.values(slots)

const props = defineProps({
  layoutName: {
    type: String,
    default: 'default',
  },
  // 保留几位小数 layoutName为number时生效
  precision: {
    type: Number,
    default: 2,
  },
  // 获取焦点打开键盘
  isOpen: {
    type: Boolean,
    default: true,
  },
})
const keyboard = ref<any>(null)
const visible = ref(false)
const inputRef = ref()
const popoverRef = ref()
const entering = ref(false)
const width = ref(1200)
if (props.layoutName == 'number') width.value = 300
const displayDefault = ref({
  '{bksp}': 'backspace',
  '{lock}': 'caps',
  '{enter}': 'enter',
  '{tab}': 'tab',
  '{shift}': 'shift',
  '{change}': 'en',
  '{space}': 'space',
  '{clear}': '清空',
  '{close}': '关闭',
  '{arrowleft}': '←',
  '{arrowright}': '→',
})

const open = () => {
  if (visible.value) return
  inputRef.value.focus()
  emits('focus')
  visible.value = true
}

const focusInput = () => {
  // 只有在当前键盘没有处于输入状态时，才关闭键盘
  if (visible.value && !entering.value) {
    handleClose()
  }

  emits('focus')

  if (props.isOpen && !entering.value) {
    visible.value = true // 显示键盘
  }
}
// const blurInput = debounce(() => {
//  if (!entering.value) {
//    handleClose()
//  } else {
//    entering.value = false
//  }
// }, 100)

// const blurInput = () => {
//   setTimeout(() => {
//     if (!entering.value) {
//       handleClose()
//     } else {
//       entering.value = false
//     }
//   }, 100)
// }

const afterEnter = () => {
  // 存在上一个实例时移除元素
  const prevKeyboard = document.querySelectorAll('.init-keyboard')
  if (prevKeyboard.length > 0) prevKeyboard[0]?.remove()
  keyboard.value = new Keyboard('simple-keyboard', {
    onChange: onChange,
    onKeyPress: onKeyPress,
    onInit: onInit,
    layout: {
      // 默认布局
      default: [
        '` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
        '{tab} q w e r t y u i o p [ ] \\',
        "{lock} a s d f g h j k l ; ' {enter}",
        '{change} z x c v b n m , . / {clear}',
        '{arrowleft} {arrowright} {space} {close}',
      ],
      // 大小写
      shift: [
        '~ ! @ # $ % ^ & * ( ) _ + {bksp}',
        '{tab} Q W E R T Y U I O P { } |',
        '{lock} A S D F G H J K L : " {enter}',
        '{change} Z X C V B N M < > ? {clear}',
        '{arrowleft} {arrowright} {space} {close}',
      ],
      // 数字布局
      number: [
        '7 8 9',
        '4 5 6',
        '1 2 3',
        '. 0 {bksp}',
        '{arrowleft} {arrowright} {clear} {close}',
      ],
    },
    layoutName: props.layoutName,
    display: displayDefault.value,
    theme: 'hg-theme-default init-keyboard', // 添加自定义class处理清空逻辑
  })
}

const beforeLeave = () => {
  visible.value = false
  entering.value = false
  inputRef.value.blur()
  displayDefault.value['{change}'] = 'en'
  document.removeEventListener('click', handlePopClose)
}

const onInit = (keyboard: any) => {
  keyboard.setInput(model.value) // 初始时同步
  keyboard.setCaretPosition(inputRef.value?.ref.selectionEnd)
  document.addEventListener('click', handlePopClose)
}
const onChange = (input: any) => {
  model.value = input
  emits('onChange', input)
}

const onKeyPress = (button: any) => {
  if (button === '{lock}') return handleLock()
  if (button === '{change}') return handleChange()
  if (button === '{clear}') return handleClear()
  if (button === '{enter}') return handleEnter()
  if (button === '{close}') return handleClose()
  if (button === '{arrowleft}') return handleArrow(0)
  if (button === '{arrowright}') return handleArrow(1)
}
const handleLock = () => {
  entering.value = true
  let currentLayout = keyboard.value.options.layoutName
  let shiftToggle = currentLayout === 'default' ? 'shift' : 'default'

  keyboard.value.setOptions({
    layoutName: shiftToggle,
  })
}
const handleChange = () => {
  entering.value = true
  let layoutCandidates = keyboard.value.options.layoutCandidates
  // 切换中英文输入法
  if (layoutCandidates != null && layoutCandidates != undefined) {
    displayDefault.value['{change}'] = 'en'
    keyboard.value.setOptions({
      layoutName: 'default',
      layoutCandidates: null,
      display: displayDefault.value,
    })
  } else {
    return
    // displayDefault.value['{change}'] = 'cn'
    // keyboard.value.setOptions({
    //   layoutName: 'default',
    //   layoutCandidates: (layout as any).layoutCandidates,
    //   display: displayDefault.value,
    // })
  }
}
const handleClear = () => {
  keyboard.value.clearInput()
  model.value = ''
}
const handleEnter = () => {
  emits('enter')
}
const handleClose = () => {
  if (props.layoutName == 'number') {
    // 处理精度
    model.value = model.value
      ?.replace(new RegExp(`(\\d+)\\.(\\d{${props.precision}}).*$`), '$1.$2')
      .replace(/\.$/, '')
  }

  // 在此处触发关闭事件
  popoverRef.value.hide()
  emits('close')

  // 键盘关闭时，触发 `onChange` 事件，确保父组件值的同步
  emits('onChange', model.value)
}

const handleArrow = (num: number) => {
  // 处理左右箭头下标位置
  const index = keyboard.value.getCaretPositionEnd()
  if (num == 0 && index - 1 >= 0) {
    keyboard.value.setCaretPosition(index - 1)
  } else if (num == 1 && index + 1 <= (model.value?.length || 0)) {
    keyboard.value.setCaretPosition(index + 1)
  }
}

const handlePopClose = (e: any) => {
  // 如果用户点击的是键盘区域，输入框区域，或者候选词框区域，我们就不关闭键盘
  if (
    (e.target as Element).closest('.keyboard-popper') ||
    e.target == inputRef.value?.ref ||
    /hg-candidate-box/.test(e.target.className)
  ) {
    entering.value = true
    const index = keyboard.value.getCaretPositionEnd()
    inputRef.value.ref.selectionStart = inputRef.value.ref.selectionEnd = index
    inputRef.value.focus()
  } else {
    // 只有在点击了输入框以外的地方才关闭键盘
    handleClose()
  }
}

const close = () => {
  handleClose()
}

onUnmounted(() => {
  // 某些情况下未触发动画关闭时销毁事件。此处销毁做后备处理
  document.removeEventListener('click', handlePopClose)
})

defineExpose({ inputRef, visible, open, close })
</script>

<style scoped lang="less">
// 变量定义
@bg-color: #ffffff;
@border-color: #dddddd;
@button-hover-bg: #f0f0f0;
@button-active-bg: #e6e6e6;
@function-key-bg: #ffcc00;
@function-key-border: #ff9900;
@disabled-bg: #f7f7f7;
@disabled-color: #cccccc;
@text-color: #333333;
@box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
@transition: all 0.3s ease;

// 覆盖 .simple-keyboard 的样式
::v-deep(.simple-keyboard) {
  width: 100% !important;
  /* 键盘宽度占满父容器 */
  max-width: 100vw !important;
  /* 限制键盘最大宽度 */
  height: auto !important;
  overflow-x: hidden !important;
  /* 禁止水平拖动 */
  overflow-y: auto !important;
  /* 如果键盘内容超长，允许垂直滚动 */
  box-sizing: border-box !important;
}

// 覆盖键盘行的样式
::v-deep(.hg-rows) {
  flex: 1; // 每一行高度平分
  display: flex; // 使用弹性布局
  flex-direction: column; // 行方向排列
}

// 覆盖键盘每一行的样式
::v-deep(.hg-row) {
  display: flex !important; // 每行按键水平排列
  gap: 1px; // 每个按键的间距
  flex: 1; // 每行高度自动调整
  justify-content: space-evenly; // 每行按键均匀分布
}

// 覆盖键盘按键样式
::v-deep(.hg-button) {
  flex: 1; // 按键宽度均分
  height: 80px; // 统一按键高度
  font-size: 24px !important; // 增大字体
  font-weight: bold !important;
  color: @text-color !important; // 按键字体颜色
  background-color: @bg-color !important; // 按键背景色
  border: 1px solid @border-color !important; // 按键边框
  border-radius: 5px !important; // 按键圆角
  display: flex !important;
  justify-content: center !important;
  align-items: center !important;
  transition: @transition !important;

  &:hover {
    background-color: @button-hover-bg !important;
  }

  &:active {
    background-color: @button-active-bg !important;
  }

  // 功能键样式
  &.hg-function {
    background-color: @function-key-bg !important;
    border-color: @function-key-border !important;
  }

  // 禁用键样式
  &.hg-disabled {
    background-color: @disabled-bg !important;
    color: @disabled-color !important;
    cursor: not-allowed !important;
  }
}

// 特殊按键（space、清空、关闭等）宽度调整
::v-deep(.hg-button-space) {
  flex: 3 !important; // 扩展宽度
}

::v-deep(.hg-button-clear),
::v-deep(.hg-button-close) {
  flex: 2 !important; // 比普通按键略大
  font-size: 16px !important;
}

// 禁用按键样式
::v-deep(.hg-disabled) {
  background-color: @disabled-bg !important;
  color: @disabled-color !important;
  cursor: not-allowed !important;
}

// 行边框调整，让行更清晰
::v-deep(.hg-row:not(:last-child)) {
  border-bottom: 1px solid #eeeeee !important; // 增加行分隔线
}

// el-popover 样式调整
::v-deep(.el-popover) {
  position: fixed !important;
  width: 100vw !important;
  /* 确保弹出层宽度占满屏幕 */
  max-width: 100vw !important;
  /* 限制最大宽度 */
  height: 100vh !important;
  /* 确保高度占满屏幕 */
  left: 0 !important;
  /* 左对齐屏幕 */
  top: 100px !important;
  /* 定位 */
  padding: 0 !important;
  background-color: transparent !important;
  transform: none !important;
  /* 移除默认偏移 */
  overflow-x: hidden !important;
  /* 禁止水平滚动 */
  overflow-y: auto !important;
  /* 垂直滚动，确保键盘内容不超出 */
}

.keyboard-wrapper {
  position: relative;
  width: 100vw;
  /* 确保键盘宽度不超出视口 */
  overflow: hidden;
  /* 防止键盘内容超出屏幕 */
}

// 输入框样式优化，确保只显示一个框
.el-input {
  font-size: 36px;
  /* 增大字体 */
  font-weight: bold;
  /* 字体加粗 */
  color: #333;
  /* 字体颜色 */
  height: 60px;
  /* 输入框高度 */
  border-radius: 8px;
  /* 圆角边框 */
  background-color: @bg-color;
  /* 背景色 */
  box-shadow: @box-shadow;
  /* 应用全局阴影变量 */
  border: none;
  /* 去除边框 */
  outline: none;
  /* 去除焦点样式 */

  &:focus-within {
    border: 2px solid #528dfe;
    /* 聚焦边框颜色 */
    box-shadow: 0 0 5px rgba(82, 141, 254, 0.5);
    /* 聚焦时阴影 */
  }

  .el-input__inner {
    font-size: inherit;
    font-weight: inherit;
    color: inherit;
    height: 100%;
    /* 占满输入框 */
    width: 100%;
    /* 宽度占满父容器 */
    border: none;
    /* 去除内部边框 */
    background-color: transparent;
    /* 背景透明 */
    outline: none;
    /* 去除焦点高亮 */
    text-align: left;
  }
}
</style>
