<script setup lang="ts">
import {computed, nextTick, onMounted, watch, watchEffect} from "vue"
import {$ref} from "vue/macros";
import {Article, ArticleWord, DefaultArticle, DisplayStatistics, ShortKeyMap, Word} from "@/types";
import {useBaseStore} from "@/stores/base";
import {usePracticeStore} from "@/stores/practice.ts";
import TypeWord from "@/components/Practice/TypeWord.vue";
import {useSettingStore} from "@/stores/setting.ts";
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
import {useOnKeyboardEventListener} from "@/hooks/event.ts";
import {cloneDeep} from "lodash-es";
import {emitter, EventKey} from "@/utils/eventBus.ts";

interface IProps {
  article: Article,
  sectionIndex: number,
  sentenceIndex: number,
  wordIndex: number,
  stringIndex: number,
}

const props = withDefaults(defineProps<IProps>(), {
  article: () => cloneDeep(DefaultArticle),
  sectionIndex: 0,
  sentenceIndex: 0,
  wordIndex: 0,
  stringIndex: 0,
})

let isPlay = $ref(false)
let articleWrapperRef = $ref<HTMLInputElement>(null)
let tabIndex = $ref(0)
let sectionIndex = $ref(0)
let sentenceIndex = $ref(0)
let wordIndex = $ref(0)
let stringIndex = $ref(0)
let input = $ref('')
let wrong = $ref('')
let isSpace = $ref(false)
let hoverIndex = $ref({
  sectionIndex: -1,
  sentenceIndex: -1,
})
const currentIndex = computed(() => {
  return `${sectionIndex}${sentenceIndex}${wordIndex}`
})
let wordData = $ref({
  words: [],
  index: -1
})

const playBeep = usePlayBeep()
const playCorrect = usePlayCorrect()
const playKeyboardAudio = usePlayKeyboardAudio()
const playWordAudio = usePlayWordAudio()
const store = useBaseStore()
const practiceStore = usePracticeStore()
const settingStore = useSettingStore()

watch(() => props.article, () => {
  sectionIndex = props.sectionIndex
  sentenceIndex = props.sentenceIndex
  wordIndex = props.wordIndex
  stringIndex = props.stringIndex

  tabIndex = 0
  practiceStore.inputWordNumber = 0
  practiceStore.wrongWordNumber = 0
  practiceStore.repeatNumber = 0
  practiceStore.total = 0
  props.article.sections.map((v, i) => {
    v.map((w, j) => {
      w.words.map(s => {
        if (!store.skipWordNamesWithSimpleWords.includes(s.name.toLowerCase()) && !s.isSymbol) {
          practiceStore.total++
        }
      })
    })
  })
  practiceStore.wrongWords = []
  practiceStore.startDate = Date.now()
  calcTranslateLocation()
}, {immediate: true})

watch(() => settingStore.dictation, () => {
  calcTranslateLocation()
})

onMounted(() => {
  emitter.on(EventKey.resetWord, () => {
    wrong = input = ''
  })
})

function calcTranslateLocation() {
  nextTick(() => {
    setTimeout(() => {
      let articleRect = articleWrapperRef.getBoundingClientRect()
      props.article.sections.map((v, i) => {
        v.map((w, j) => {
          let location = i + '-' + j
          let wordClassName = `.word${location}`
          let word = document.querySelector(wordClassName)
          let wordRect = word.getBoundingClientRect()
          let translateClassName = `.translate${location}`
          let translate: HTMLDivElement = document.querySelector(translateClassName)

          translate.style.opacity = '1'
          translate.style.top = wordRect.top - articleRect.top - 22 + 'px'
          // @ts-ignore
          translate.firstChild.style.width = wordRect.left - articleRect.left + 'px'
          // console.log(word, wordRect.left - articleRect.left)
          // console.log('word-wordRect', wordRect)
        })
      })
    }, 300)
  })
}

function play() {
  return playWordAudio('article1')
  if (isPlay) {
    isPlay = false
    return window.speechSynthesis.pause();
  }
  let msg = new SpeechSynthesisUtterance();
  msg.text = 'article1'
  msg.rate = 0.5;
  msg.pitch = 1;
  msg.lang = 'en-US';
  // msg.lang = 'zh-HK';
  isPlay = true
  window.speechSynthesis.speak(msg);
}

function onKeyDown(e: KeyboardEvent) {
  if (tabIndex !== 0) return
  if (!props.article.sections.length) return
  // console.log('keyDown', e.key, e.code, e.keyCode)
  wrong = ''
  let currentSection = props.article.sections[sectionIndex]
  let currentSentence = currentSection[sentenceIndex]
  let currentWord: ArticleWord = currentSentence.words[wordIndex]

  const nextWord = () => {
    isSpace = false
    stringIndex = 0
    wordIndex++

    if (!store.skipWordNamesWithSimpleWords.includes(currentWord.name.toLowerCase()) && !currentWord.isSymbol) {
      practiceStore.inputWordNumber++
    }

    if (!currentSentence.words[wordIndex]) {
      wordIndex = 0
      sentenceIndex++
      if (!currentSection[sentenceIndex]) {
        sentenceIndex = 0
        sectionIndex++

        if (!props.article.sections[sectionIndex]) {
          console.log('打完了')
        }
      } else {
        if (settingStore.dictation) {
          calcTranslateLocation()
        }
        playWordAudio(currentSection[sentenceIndex].text)
      }
    }
  }

  const nextSentence = () => {
    // tabIndex = 1
    // // wordData.words = practiceStore.wrongWords
    // wordData.words = [
    //   {"name": "pharmacy", "trans": ["药房；配药学，药剂学；制药业；一批备用药品"], "usphone": "'fɑrməsi", "ukphone": "'fɑːməsɪ"},
    //   // {"name": "foregone", "trans": ["过去的；先前的；预知的；预先决定的", "发生在…之前（forego的过去分词）"], "usphone": "'fɔrɡɔn", "ukphone": "fɔː'gɒn"}, {"name": "president", "trans": ["总统；董事长；校长；主席"], "usphone": "'prɛzɪdənt", "ukphone": "'prezɪd(ə)nt"}, {"name": "plastic", "trans": ["塑料的；（外科）造型的；可塑的", "塑料制品；整形；可塑体"], "usphone": "'plæstɪk", "ukphone": "'plæstɪk"}, {"name": "provisionally", "trans": ["临时地，暂时地"], "usphone": "", "ukphone": ""}, {"name": "incentive", "trans": ["动机；刺激", "激励的；刺激的"], "usphone": "ɪn'sɛntɪv", "ukphone": "ɪn'sentɪv"}, {"name": "calculate", "trans": ["计算；以为；作打算"], "usphone": "'kælkjulet", "ukphone": "'kælkjʊleɪt"}
    // ]
    // return

    isSpace = false
    stringIndex = 0
    wordIndex = 0
    input = wrong = ''

    //todo 计得把略过的单词加上统计里面去
    // if (!store.skipWordNamesWithSimpleWords.includes(currentWord.name.toLowerCase()) && !currentWord.isSymbol) {
    //   practiceStore.inputNumber++
    // }

    sentenceIndex++
    if (!currentSection[sentenceIndex]) {
      sentenceIndex = 0
      sectionIndex++
      if (!props.article.sections[sectionIndex]) {
        console.log('打完了')
        if (practiceStore.wrongWordNumber === 0) {
          // if (false) {
          console.log('这章节完了')
          let now = Date.now()
          let stat: DisplayStatistics = {
            startDate: practiceStore.startDate,
            endDate: now,
            spend: now - practiceStore.startDate,
            total: practiceStore.total,
            correctRate: -1,
            wrongWordNumber: practiceStore.wrongWordNumber,
            wrongWords: practiceStore.wrongWords,
          }
          stat.correctRate = 100 - Math.trunc(((stat.wrongWordNumber) / (stat.total)) * 100)
          emitter.emit(EventKey.openStatModal, stat)
        } else {
          tabIndex = 1
          wordData.words = practiceStore.wrongWords
        }
      }
    } else {
      if (settingStore.dictation) {
        calcTranslateLocation()
      }
      playWordAudio(currentSection[sentenceIndex].text)
    }
  }
  //非英文模式下，输入区域的 keyCode 均为 229时，
  if ((e.keyCode >= 65 && e.keyCode <= 90)
      || (e.keyCode >= 48 && e.keyCode <= 57)
      || e.code === 'Space'
      || e.code === 'Slash'
      || e.code === 'Quote'
      || e.code === 'Comma'
      || e.code === 'BracketLeft'
      || e.code === 'BracketRight'
      || e.code === 'Period'
      || e.code === 'Minus'
      || e.code === 'Equal'
      || e.code === 'Semicolon'
      || e.code === 'Backquote'
      || e.keyCode === 229
  ) {
    if (isSpace) {
      if (e.code === 'Space') {
        nextWord()
      } else {
        wrong = ' '
        playBeep()

        setTimeout(() => {
          wrong = ''
          wrong = input = ''
        }, 500)
      }
      playKeyboardAudio()
    } else {
      let letter = e.key

      let key = currentWord.name[stringIndex]
      // console.log('key', key,)

      let isWrong = false
      if (settingStore.ignoreCase) {
        isWrong = key.toLowerCase() !== letter.toLowerCase()
      } else {
        isWrong = key !== letter
      }
      if (!isWrong) {
        input += letter
        wrong = ''
        // console.log('匹配上了')
        stringIndex++
        //如果当前词没有index，说明这个词完了，下一个是空格
        if (!currentWord.name[stringIndex]) {
          input = wrong = ''
          if (!currentWord.isSymbol) {
            playCorrect()
          }
          if (currentWord.nextSpace) {
            isSpace = true
          } else {
            nextWord()
          }
        }
      } else {
        if (!store.wrongWordDict.originWords.find((v: Word) => v.name.toLowerCase() === currentWord.name.toLowerCase())) {
          store.wrongWordDict.originWords.push(currentWord)
          store.wrongWordDict.words.push(currentWord)
          store.wrongWordDict.chapterWords = [store.wrongWordDict.words]
        }

        if (!store.skipWordNamesWithSimpleWords.includes(currentWord.name.toLowerCase())) {
          if (!practiceStore.wrongWords.find((v) => v.name.toLowerCase() === currentWord.name.toLowerCase())) {
            practiceStore.wrongWords.push(currentWord)
            practiceStore.wrongWordNumber++
          }
        }

        wrong = letter
        playBeep()
        setTimeout(() => {
          wrong = ''
        }, 500)
        // console.log('未匹配')
      }
      playKeyboardAudio()
    }
  } else {
    switch (e.key) {
      case 'Backspace':
        if (wrong) {
          wrong = ''
        } else {
          input = input.slice(0, -1)
        }
        break
      case ShortKeyMap.Collect:

        break
      case ShortKeyMap.Remove:
        break
      case ShortKeyMap.Ignore:
        nextSentence()
        break
      case ShortKeyMap.Show:
        if (settingStore.allowWordTip) {
          hoverIndex = {
            sectionIndex: sectionIndex,
            sentenceIndex: sentenceIndex,
          }
        }
        break
    }
  }

  // console.log(
  //     'sectionIndex', sectionIndex,
  //     'sentenceIndex', sentenceIndex,
  //     'wordIndex', wordIndex,
  //     'stringIndex', stringIndex,
  // )
  e.preventDefault()
}

function onKeyUp() {
  hoverIndex = {
    sectionIndex: -1,
    sentenceIndex: -1,
  }
}

useOnKeyboardEventListener(onKeyDown, onKeyUp)

// useEventListener('keydown', onKeyDown)
// useEventListener('keyup', onKeyUp)

function playWord(word: ArticleWord) {
  playWordAudio(word.name)
}

function currentWordInput(word: ArticleWord, i: number, i2: number,) {
  let str = word.name.slice(input.length + wrong.length, input.length + wrong.length + 1)
  if (word.isSymbol) {
    return str
  }
  if (hoverIndex.sectionIndex === i && hoverIndex.sentenceIndex === i2) {
    return str
  }

  if (settingStore.dictation) {
    return '_'
  }
  return str
}

function currentWordEnd(word: ArticleWord, i: number, i2: number,) {
  let str = word.name.slice(input.length + wrong.length + (wrong ? 0 : 1))
  if (hoverIndex.sectionIndex === i && hoverIndex.sentenceIndex === i2) {
    return str
  }

  if (settingStore.dictation) {
    return str.split('').map(v => '_').join('')
  }
  return str
}

function otherWord(word: ArticleWord, i: number, i2: number, i3: number) {
  let str = word.name
  if (word.isSymbol) {
    return str
  }

  if (hoverIndex.sectionIndex === i && hoverIndex.sentenceIndex === i2) {
    return str
  }

  //剩100是因为，可能存在特殊情况，比如003,010这种，0 12 24，100
  if (sectionIndex * 10000 + sentenceIndex * 100 + wordIndex < i * 10000 + i2 * 100 + i3
      && settingStore.dictation
  ) {
    return str.split('').map(v => '_').join('')
  }
  return str
}

</script>

<template>
  <div class="type-wrapper">
    <div class="swiper-wrapper content">
      <div class="swiper-list" :class="`step${tabIndex}`">
        <div class="swiper-item">
          <div class="article-wrapper">
            <header>
              <div class="title">{{ props.article.title }}</div>
              <div class="titleTranslate" v-if="settingStore.translate">{{ props.article.titleTranslate }}</div>
            </header>
            <div class="article-content" ref="articleWrapperRef">
              <article>
                <div class="section"
                     v-for="(section,indexI) in props.article.sections">
                <span class="sentence"
                      :class="[
                          sectionIndex === indexI && sentenceIndex === indexJ && settingStore.dictation
                          ?'dictation':''
                      ]"
                      @mouseenter="settingStore.allowWordTip && (hoverIndex = {sectionIndex : indexI,sentenceIndex :indexJ})"
                      @mouseleave="hoverIndex = {sectionIndex : -1,sentenceIndex :-1}"
                      @click="playWordAudio(sentence.text)"
                      v-for="(sentence,indexJ) in section">
                  <span
                      v-for="(word,indexW) in sentence.words"
                      class="word"
                      :class="[(sectionIndex>indexI
                        ?'wrote':
                        (sectionIndex>=indexI &&sentenceIndex>indexJ)
                        ?'wrote' :
                        (sectionIndex>=indexI &&sentenceIndex>=indexJ && wordIndex>indexW)
                        ?'wrote':
                         (sectionIndex>=indexI &&sentenceIndex>=indexJ && wordIndex>=indexW && stringIndex>=word.name.length)
                        ?'wrote':
                        ''),
                        (`${indexI}${indexJ}${indexW}` === currentIndex && !isSpace && wrong )?'word-wrong':'',
                        indexW === 0 && `word${indexI}-${indexJ}`
                        ]"
                      @click="playWord(word)">
                    <span v-if="`${indexI}${indexJ}${indexW}` === currentIndex && !isSpace">
                      <span class="input" v-if="input">{{ input }}</span>
                      <span class="wrong" :class="wrong === ' ' && 'bg-wrong'" v-if="wrong">{{ wrong }}</span>
                      <span class="bottom-border" v-else>{{ currentWordInput(word, indexI, indexJ) }}</span>
                      <span>{{ currentWordEnd(word, indexI, indexJ,) }}</span>
                    </span>
                    <span v-else>{{ otherWord(word, indexI, indexJ, indexW) }}</span>
                    <span
                        v-if="word.nextSpace"
                        :class="[
                            `${indexI}${indexJ}${indexW}`,
                            (`${indexI}${indexJ}${indexW}` === currentIndex && isSpace && wrong) && 'bg-wrong',
                            (`${indexI}${indexJ}${indexW}` === currentIndex && isSpace && !wrong) && 'bottom-border',
                            (`${indexI}${indexJ}${indexW}` === currentIndex && isSpace && !wrong && settingStore.dictation) && 'word-space',
                        ]">
                      {{
                        (`${indexI}${indexJ}${indexW}` === currentIndex && isSpace && settingStore.dictation) ? '_' : ' '
                      }}
                    </span>
                  </span>
                </span>
                </div>
              </article>
              <div class="translate" v-show="settingStore.translate">
                <template v-for="(v,i) in props.article.sections">
                  <div class="row"
                       :class="`translate${i+'-'+j}`"
                       v-for="(item,j) in v">
                    <span class="space"></span>
                    <Transition name="fade">
                      <span class="text" v-if="item.translate">{{ item.translate }}</span>
                    </Transition>
                  </div>
                </template>
              </div>
            </div>
          </div>
        </div>
        <div class="swiper-item">
          <TypeWord
              :words="wordData.words"
              :index="wordData.index"
              v-if="tabIndex === 1"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
@import "@/assets/css/style.scss";

.wrote {
  //color: green;
  color: rgb(22, 163, 74);
}

.type-wrapper {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;

  .content {
    width: 1000px;
  }

  .article-wrapper {

    header {
      .title {
        text-align: center;
        color: rgba(gray, .8);
        font-size: 36rem;
        font-weight: 500;
        word-spacing: 3rem;
        //opacity: 0;
      }

      .titleTranslate {
        @extend .title;
        font-size: 20rem;
      }
    }

    .article-content {
      position: relative;
      //opacity: 0;
    }

    article {
      //height: 100%;
      font-size: 24rem;
      line-height: 2.5;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
      color: gray;
      word-break: keep-all;
      word-wrap: break-word;
      white-space: pre-wrap;
      padding-top: 20rem;

      .section {
        margin-bottom: $space;

        .sentence {
          transition: all .3s;

          &.dictation {
            letter-spacing: 3rem;
          }
        }

        .word {
          display: inline-block;
        }
      }
    }

    .translate {
      pointer-events: none;
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      width: 100%;
      font-size: 18rem;
      color: gray;
      line-height: 3.5;
      letter-spacing: 3rem;
      //display: none;

      .row {
        position: absolute;
        left: 0;
        width: 100%;
        opacity: 0;

        .space {
          transition: all .3s;
          display: inline-block;
        }
      }
    }
  }

  .word-space {
    position: relative;
    color: gray;

    &::after {
      content: ' ';
      position: absolute;
      width: 1.5rem;
      height: 4rem;
      background: gray;
      bottom: 2rem;
      right: 2.5rem;
    }

    &::before {
      content: ' ';
      position: absolute;
      width: 1.5rem;
      height: 4rem;
      background: gray;
      bottom: 2rem;
      left: 0;
    }
  }

  .bottom-border {
    animation: underline 1s infinite steps(1, start);
  }

  .input {
    //font-weight: bold;
    color: var(--color-main-active);
  }

  .wrong {
    color: rgba(red, 0.6);
  }

  .word-wrong {
    display: inline-block;
    animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
  }

  .bg-wrong {
    display: inline-block;
    color: gray;
    background: rgba(red, 0.6);
    animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
  }
}

.swiper-wrapper {
  height: 100%;
  width: 100%;
  overflow: hidden;

  .swiper-list {
    transition: transform .3s;
    height: 200%;

    .swiper-item {
      height: 50%;
      overflow: auto;
      display: flex;
    }
  }

  .step1 {
    transform: translate3d(0, -50%, 0);
  }
}

@keyframes underline {
  0%, 100% {
    border-left: 1.3rem solid black;
  }
  50% {
    border-left: 1.3rem solid transparent;
  }
}
</style>