<template>
  <div
    ref="eyeRef"
    class="eyeball"
    :style="{
      width: `${props.size}px`,
      height: props.isBlinking ? '2px' : `${props.size}px`,
      backgroundColor: props.eyeColor,
    }"
  >
    <template v-if="!props.isBlinking">
      <div
        class="eyeball-pupil"
        :style="{
          width: `${props.pupilSize}px`,
          height: `${props.pupilSize}px`,
          backgroundColor: props.pupilColor,
          transform: `translate(${pupilOffsetX.value}px, ${pupilOffsetY.value}px)`,
        }"
      ></div>
    </template>
  </div>
</template>
<script setup>
import { ref, watch, computed, onMounted, onUnmounted } from "vue";
const props = defineProps({
  size: { type: Number, default: 48 },
  pupilSize: { type: Number, default: 16 },
  maxDistance: { type: Number, default: 10 },
  eyeColor: { type: String, default: "white" },
  pupilColor: { type: String, default: "black" },
  isBlinking: { type: Boolean, default: false },
  forceLookX: { type: Number, default: undefined },
  forceLookY: { type: Number, default: undefined },
});

const eyeRef = ref();
const pupilOffsetX = ref(0);
const pupilOffsetY = ref(0);
const mouseX = ref(0);
const mouseY = ref(0);

const updateMousePosition = (e) => {
  mouseX.value = e.clientX;
  mouseY.value = e.clientY;
  updateOffset();
};

const updateOffset = () => {
  if (!eyeRef.value) return;
  if (props.forceLookX !== undefined && props.forceLookY !== undefined) {
    pupilOffsetX.value = props.forceLookX;
    pupilOffsetY.value = props.forceLookY;
    return;
  }
  const rect = eyeRef.value.getBoundingClientRect();
  const centerX = rect.left + rect.width / 2;
  const centerY = rect.top + rect.height / 2;
  const deltaX = mouseX.value - centerX;
  const deltaY = mouseY.value - centerY;
  const distance = Math.min(Math.sqrt(deltaX ** 2 + deltaY ** 2), props.maxDistance);
  const angle = Math.atan2(deltaY, deltaX);
  pupilOffsetX.value = Math.cos(angle) * distance;
  pupilOffsetY.value = Math.sin(angle) * distance;
};

onMounted(() => {
  window.addEventListener("mousemove", updateMousePosition);
  updateOffset();
});
onUnmounted(() => {
  window.removeEventListener("mousemove", updateMousePosition);
});
watch(
  () => [props.forceLookX, props.forceLookY],
  () => updateOffset(),
);
</script>

<style scoped>
/* 眼球组件 */
.eyeball {
  border-radius: 9999px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition-property: all;
  transition-duration: 150ms;
  transition-timing-function: ease;
  overflow: hidden;
}

.eyeball-pupil {
  border-radius: 9999px;
  transition: transform 0.1s ease-out;
}
</style>
