<script setup lang="ts">
/*
 * 组件名: PictureNaming
 * 组件用途: 图片命名
 * 创建日期: 2024/8/20
 * 编写者: JutarryWu
 */
import { shuffle } from 'lodash-es'
import { showSuccessToast } from 'vant'
import Topics from './Topics.json'
import GameAPI, { type GameResultVO, type GameVO } from '@/api/game'

interface IData {
  choices?: string[]
  img?: string
  seconds?: number
  correct?: string
  isRight?: boolean
  checked?: boolean
  score?: number
  reactionTime?: number
}

const router = useRouter()
const VoiceImpRef = ref()
const subjectInfo = ref<GameVO>({})
const showCountDown = ref(true) // 显示倒计时
const showImg = ref(true) // 显示图片
const showText = ref(false) // 显示文字
const musicFlag = ref(true) // 页面音乐开关
const userCanClickFlag = ref(false) // 用户是否可以点击开关
const showDataArr = ref<IData[]>([])
const seconds = [3000, 2000, 1500]
const currentIndex = ref(0) // 当前索引
const selectiveIndex = ref(-1) //  用户选择的索引
const textTimeout = ref<NodeJS.Timeout | null>(null)
const imgTimeout = ref<NodeJS.Timeout | null>(null)
const onceTimer = ref<NodeJS.Timeout | null>(null)
let onceStart = 0 // 试次开始时间

function initData() {
  for (let i = 0; i < 3; i++) {
    const tempArr = []
    for (let j = 0; j < 15; j++) {
      tempArr.push({
        choices: shuffle(Topics[i * 15 + j]),
        img: `/static/image/game/name/${i * 15 + j}.png`,
        seconds: seconds[i], // 图片显示时长
        correct: Topics[i * 15 + j][0], // 正确答案
        isRight: false, // 是否正确
        score: 0, // 正确： 1， 错误：0
        reactionTime: 4000, // 反应时间(ms)
        checked: false, // 是否选过
      })
    }
    showDataArr.value = [...showDataArr.value, ...shuffle(tempArr)]
  }
}

function musicClick(flag: number) {
  musicFlag.value = !musicFlag.value
  if (musicFlag.value) {
    VoiceImpRef.value.videoPlay('click')
    VoiceImpRef.value.videoPlay('bg', flag)
  }
  else {
    VoiceImpRef.value.videoPause('bg')
  }
}

function choiceClick(item: string, index: number) {
  if (!userCanClickFlag.value) {
    return
  }
  if (!showDataArr.value[currentIndex.value].checked) {
    showDataArr.value[currentIndex.value].checked = true
    selectiveIndex.value = index
    if (item === showDataArr.value[currentIndex.value].correct) {
      showDataArr.value[currentIndex.value].isRight = true
      showDataArr.value[currentIndex.value].score = 1
      showDataArr.value[currentIndex.value].reactionTime = Number((performance.now() - onceStart).toFixed(3))
      if (musicFlag.value) {
        VoiceImpRef.value.videoPlay('right')
      }
    }
    else {
      if (musicFlag.value) {
        VoiceImpRef.value.videoPlay('error')
      }
    }
    clearTimeout(textTimeout.value)
    clearTimeout(imgTimeout.value)
    clearTimeout(onceTimer.value)
    setTimeout(() => {
      userCanClickFlag.value = false
      showText.value = false
      showImg.value = false
      currentIndex.value++
      nextOnce()
    }, 900)
  }
}

function nextOnce() {
  if (currentIndex.value < showDataArr.value.length) {
    onceStart = performance.now()
    selectiveIndex.value = -1
    showImg.value = true

    // 隐藏图片
    imgTimeout.value = setTimeout(() => {
      showImg.value = false
      showText.value = true
      userCanClickFlag.value = true
      // 隐藏文字
      textTimeout.value = setTimeout(() => {
        showText.value = false
      }, 3000)
    }, showDataArr.value[currentIndex.value].seconds)

    // 如果用户未点击，自动清除定时器，进入下一个试次
    onceTimer.value = setTimeout(() => {
      userCanClickFlag.value = false
      showText.value = false
      showImg.value = false
      clearTimeout(textTimeout.value)
      clearTimeout(imgTimeout.value)
      clearTimeout(onceTimer.value)
      currentIndex.value++
      nextOnce()
    }, 7000)
  }
  else {
    submit()
  }
}

function submit() {
  let correctNum = 0
  let wrongNum = 0
  let accuracy = 0
  let totalScore = 0
  let averageReactionTimeForCorrect = 0
  showDataArr.value.forEach((item) => {
    if (item.isRight) {
      correctNum++
      totalScore++
      averageReactionTimeForCorrect += item.reactionTime
    }
  })
  wrongNum = 45 - correctNum
  accuracy = Number((correctNum / 45).toFixed(4))
  averageReactionTimeForCorrect = Number((averageReactionTimeForCorrect / correctNum).toFixed(3))

  const data: GameResultVO = {
    finish: '1',
    gameId: subjectInfo.value.id,
    gameName: subjectInfo.value.name,
    paramList: [
      {
        code: 'correctNum',
        name: '正确数',
        value: correctNum,
      },
      {
        code: 'wrongNum',
        name: '错误数',
        value: wrongNum,
      },
      {
        code: 'accuracy',
        name: '正确率',
        value: accuracy,
      },
      {
        code: 'totalScore',
        name: '得分',
        value: totalScore,
      },
      {
        code: 'averageReactionTimeForCorrect',
        name: '正确点击的反应时长均值',
        value: `${averageReactionTimeForCorrect}ms`,
      },
    ],
    userId: sessionStorage.getItem('userId'),
  }
  GameAPI.add(data).then(() => {
    showSuccessToast({
      className: 'rotate-toast',
      message: '本次训练已结束',
    })
    setTimeout(() => {
      router.go(-1)
    }, 1300)
  })
}

function exec() {
  showCountDown.value = false
  nextOnce()
}

onMounted(() => {
  const temp = sessionStorage.getItem('subjectInfo')
  if (temp) {
    subjectInfo.value = JSON.parse(temp)
  }
  if (musicFlag.value) {
    VoiceImpRef.value.videoPlay('bg')
  }
  initData()
})

onBeforeUnmount(() => {
  clearInterval(onceTimer.value)
})
</script>

<template>
  <section class="app-container">
    <van-nav-bar class="self-nav-bar" :title="subjectInfo.name" left-arrow @click-left="router.go(-1)">
      <template #right>
        <img v-if="musicFlag" src="/static/image/game/video/play.png" alt="" class="h-[34px] w-[34px]" @click="musicClick(0)">
        <img v-else src="/static/image/game/video/stop.png" alt="" class="h-[34px] w-[34px]" @click="musicClick(1)">
      </template>
    </van-nav-bar>
    <count-down v-if="showCountDown" :time="5" color="#fff" @end-count-down="exec" />
    <VoiceImp ref="VoiceImpRef" />

    <div v-if="!showCountDown && currentIndex < showDataArr.length" class="absolute-center flex-column h-[78%] w-[100%]">
      <div class="center-div flex-center ml-[4%] h-[390px] w-[92%]">
        <img v-if="showImg" :src="showDataArr[currentIndex].img" alt="" class="h-[50%] w-[58%]">
      </div>
      <div class="mt-[20px] h-[80px] w-[100%] flex-row justify-around text-center text-[42px] text-[#3A3A3AE2] line-height-[80px]">
        <div
          v-for="(item, index) in showDataArr[currentIndex].choices"
          :key="index"
          class="text-area relative h-[80px] w-[80px] rounded-[20px] text-center line-height-[80px] shadow-lg"
          @click="choiceClick(item, index)"
        >
          <span v-if="showText">{{ item }}</span>
          <WuIsCorrect
            v-if="selectiveIndex === index && showDataArr[currentIndex].checked"
            :correct="showDataArr[currentIndex].isRight"
          />
        </div>
      </div>
    </div>
  </section>
</template>

<style scoped lang="less">
.app-container {
  background-image: url('/static/image/game/bg-pic-naming.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center center;

  :deep(.van-nav-bar) {
    .van-nav-bar__title {
      color: #fff;
    }

    .van-icon {
      color: #fff;
    }
  }

  .center-div {
    background-image: url('/static/image/game/bg-center.png');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    background-position: center center;
  }

  .text-area {
    background-image: url('/static/image/game/bg-text.png');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    background-position: center center;
  }
}
</style>
