<template>
  <div class="slider-verify-container w-320px my-3" v-loading="isResetting">
    <div class="relative">
      <img :src="captcha.canvasSrc" alt="验证图" draggable="false"/>
      <img
        ref="blockImage"
        :src="captcha.blockSrc"
        class="absolute left-0"
        :style="{top: captcha.blockY + 'px', transform: `translateX(${blockX}px)`}"
        alt="缺失的块"
        draggable="false"
      />
    </div>
    <div class="relative bg-white text-center line-height-50px h-50px shadow-inset shadow-black shadow-sm bg-opacity-50">
      <span v-show="!isDragging">向右拖动滑块来验证</span>
      <div
        ref="sliderBlock"
        class="absolute top-0 left-0 mt-5px ml-8px w-49px h-40px bg-blue cursor-pointer rounded-5px"
        :class="{'shadow-inset shadow-black shadow-sm': isDragging,'cursor-not-allowed':isResetting}"
        :style="{transform: `translateX(${currentX}px)`}"
        @mousedown="startDrag"
        @mousemove="onDrag"
        @mouseup="endDrag"
      ></div>
    </div>
    <div class="text-black text-5 rounded-50%">
      <el-icon class="cursor-pointer hover:text-cyan" @click="reset">
        <RefreshRight />
      </el-icon>
    </div>
  </div>
</template>

<script setup lang="ts">
import request from '@/utils/request'
import { ElMessage } from 'element-plus'
import { ref } from 'vue'
import { RefreshRight } from '@element-plus/icons-vue'

interface Captcha {
  nonceStr: string,
  value: string,
  canvasSrc: string,
  canvasWidth: number,
  canvasHeight: number,
  blockSrc: string,
  blockWidth: number,
  blockHeight: number,
  blockRadius: number,
  blockX: number,
  blockY: number,
  place: number,
}
interface SliderVerifyResponse extends AxiosResponse{
  data: Captcha
}
const captcha = ref<Captcha>({
  blockHeight: 0,
  blockRadius: 0,
  blockSrc: '',
  blockWidth: 0,
  blockX: 0,
  blockY: 0,
  canvasHeight: 0,
  canvasSrc: '',
  canvasWidth: 0,
  nonceStr: '',
  place: 0,
  value: ''
})
const sliderBlock = ref<HTMLElement | null>(null)
const blockImage = ref<HTMLElement | null>(null)
const isDragging = ref(false);
const startX = ref(0)
const currentX = ref(0)
const blockX = ref(0)
const isResetting = ref(false);
const startTime = ref(0);
const emits = defineEmits(['verify','resetSlider']);
const getImg = async () => {
  const res = await request.post<Captcha, SliderVerifyResponse>("/captchaSlider/getCaptcha", {})
  if (res.code !== 200) {
    ElMessage.error("当次获取验证图失败")
  }
  captcha.value = res.data
  blockX.value = captcha.value.blockX
}

const init = () => {
  getImg()
}

const startDrag = (event: MouseEvent) => {
  startTime.value = Date.now()
  if (sliderBlock.value && !isResetting.value) {
    isDragging.value = true
    startX.value = event.clientX - sliderBlock.value.offsetLeft
  }
}

const onDrag = (event: MouseEvent) => {
  event.preventDefault()
  if (isDragging.value && sliderBlock.value) {
    currentX.value = event.clientX - startX.value
    if (currentX.value < 0) currentX.value = 0
    if (currentX.value > 252) currentX.value = 252
    blockX.value = currentX.value
  }
}

const endDrag = () => {
  if(Date.now() - startTime.value > 10000){
    emits('resetSlider');
    return
  }
  if(Date.now() - startTime.value < 100){
    reset()
    return
  }
  if (isDragging.value) {
    emits('verify', captcha.value.nonceStr, currentX.value);
    isDragging.value = false
    isResetting.value = true
  }
}

const reset =async ()=>{
  await getImg();
  isResetting.value = false
  isDragging.value = false
  blockX.value = 0;
  currentX.value = 0;
}
defineExpose({reset});
init()
</script>
