<template>
  <svg xmlns="http://www.w3.org/2000/svg" :width="props.width" :height="props.height" viewBox="0 0 1600 1600">
    <def>
      <filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
        <feGaussianBlur in="SourceAlpha" stdDeviation="20" result="blur" />
        <feColorMatrix result="bluralpha" type="matrix" :values="colorMatrix" />
        <feOffset in="bluralpha" dx="20" dy="20" result="offsetBlur" />
        <feMerge>
          <feMergeNode in="offsetBlur" />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>
    </def>
    <g>
      <rect width="800" height="800" x="400" y="400" fill="#464646" rx="20" />
      <rect width="700" height="700" x="450" y="450" fill="#eaeaea" rx="20" />
      <circle r="20" cx="1075" cy="1075" fill="#171717" />
      <circle r="20" cx="1075" cy="525" fill="#171717" />
      <circle r="20" cx="525" cy="525" fill="#171717" />
      <circle r="20" cx="525" cy="1075" fill="#171717" />
    </g>
    <g>
      <linearGradient id="normal" gradientTransform="rotate(45 0 0)">
        <stop stop-color="#4b4b4b" offset="0" />
        <stop stop-color="#171717" offset="1" />
      </linearGradient>
      <linearGradient id="pressed" gradientTransform="rotate(45 0 0)">
        <stop stop-color="#171717" offset="0" />
        <stop stop-color="#4b4b4b" offset="1" />
      </linearGradient>
      <circle class="shadow" r="220" cx="800" cy="800" fill="black" />
      <circle class="light" @mousedown="toggleButtonState(true)" @mouseup="toggleButtonState(false)" 
        @contextmenu.prevent="openContextMenu($event)" :r="btnHeight" cx="800" cy="800"
        fill-opacity="0.9" style="pointer-events: auto;"/>
      <text 
        v-if="bindKey"
        x="800" 
        y="800"
        font-size="310"
        text-anchor="middle"
        dominant-baseline="central"
        fill="#ccc"
        style="font-family: Arial; filter: url(#shadow); user-select: none; pointer-events: none; mix-blend-mode: overlay;"
      >
        {{ bindKey.toUpperCase() }}
      </text>
    </g>
  </svg>
  <div v-if="showContextMenu"
       :style="{ top: contextMenuY + 'px', left: contextMenuX + 'px' }"
       @click.stop
       class="fixed z-50 border border-base-300 bg-base-100 rounded-md shadow-lg">
    <div class="px-4 py-2 cursor-pointer whitespace-nowrap text-base-content hover:bg-base-200"
         @click="startBinding">
      <span v-if="isBinding">请输入</span>
      <span v-else>绑定按键: {{ bindKey ? bindKey.toUpperCase() : '未绑定' }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

interface Props {
  width?: string | number
  height?: string | number
}
const bindKey = ref('');
let isKeyPressed = false;
const props = withDefaults(defineProps<Props>(), {
  width: 160,
  height: 160,
})

const btnHeight = ref(200)

const colorMatrix = ref("1 0 0 0   0  0 1 0 0   0  0 0 1 0   0  0 0 0 1   0")

function toggleButtonState(isPressed: boolean) {
  btnHeight.value = isPressed ? 210 : 200;
  colorMatrix.value = isPressed 
    ? "1 0 0 0   0  0 1 0 0   0  0 0 1 0   0  0 0 0 0.7   0"
    : "1 0 0 0   0  0 1 0 0   0  0 0 1 0   0  0 0 0 1   0";
}

const isBinding = ref(false);
const showContextMenu = ref(false);
const contextMenuX = ref(0);
const contextMenuY = ref(0);

function openContextMenu(e: MouseEvent) {
  contextMenuX.value = e.clientX;
  contextMenuY.value = e.clientY;
  showContextMenu.value = true;
}

function closeContextMenu() {
  showContextMenu.value = false;
}

function startBinding() {
  if (isBinding.value) return;
  isBinding.value = true;
  window.addEventListener('keydown', onBindingKeyDown, { once: true });
}

function onBindingKeyDown(e: KeyboardEvent) {
  bindKey.value = e.key.toLowerCase();
  isBinding.value = false;
}

function handleKeyDown(e: KeyboardEvent) {
  if (e.key.toLowerCase() === bindKey.value && !isKeyPressed) {
    isKeyPressed = true;
    toggleButtonState(true);
  }
}

function handleKeyUp(e: KeyboardEvent) {
  if (e.key.toLowerCase() === bindKey.value) {
    isKeyPressed = false;
    toggleButtonState(false);
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleKeyDown);
  window.addEventListener('keyup', handleKeyUp);
  window.addEventListener('click', closeContextMenu);
});

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown);
  window.removeEventListener('keyup', handleKeyUp);
  window.removeEventListener('click', closeContextMenu);
});
</script>

<style scoped lang="postcss">
circle {
  transition: all 20ms ease-in-out;
}

.shadow {
  filter: url(#shadow);
}

.light:active {
  fill: url(#pressed);
}

.light {
  fill: url(#normal);
}
</style>
