<!-- eslint-disable vue/no-v-html -->
<template>
  <div class="select-preview" :style="getAreaStyle()">
    <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />

    <div class="main" :style="getMainStyle()">
      <AudioFill :file-id="data.audio_file_id" />
      <div class="fill-wrapper">
        <p v-for="(item, i) in modelEssay" :key="i">
          <template v-for="(li, j) in item">
            <template v-if="li.type === 'text'">
              <PinyinText
                v-if="isEnable(data.property.view_pinyin)"
                :key="`${i}-${j}`"
                class="content"
                :paragraph-list="li.paragraph_list"
                :pinyin-position="data.property.pinyin_position"
                :is-preview="true"
              />
              <span v-else :key="j" v-html="convertText(sanitizeHTML(li.content))"></span>
            </template>
            <template v-if="li.type === 'input'">
              <template v-if="data.property.fill_type === fillTypeList[0].value">
                <el-input
                  :key="j"
                  v-model="li.content"
                  :disabled="disabled"
                  :class="[data.property.fill_font, ...computedAnswerClass(li.mark)]"
                  :style="[{ width: Math.max(80, li.content.length * 21.3) + 'px' }]"
                />
              </template>

              <template v-else-if="data.property.fill_type === fillTypeList[1].value">
                <el-popover :key="j" placement="top" trigger="click">
                  <div class="word-list">
                    <span
                      v-for="{ content, mark } in data.word_list"
                      :key="mark"
                      class="word-item"
                      @click="handleSelectWord(content, mark, li)"
                    >
                      {{ content }}
                    </span>
                  </div>

                  <el-input
                    slot="reference"
                    v-model="li.content"
                    :readonly="true"
                    :class="[data.property.fill_font, ...computedAnswerClass(li.mark)]"
                    class="pinyin"
                    :style="[{ width: Math.max(80, li.content.length * 21.3) + 'px' }]"
                  />
                </el-popover>
              </template>

              <template v-else-if="data.property.fill_type === fillTypeList[2].value">
                <span :key="j" class="write-click" @click="handleWriteClick(li.mark)">
                  <img
                    v-show="li.write_base64"
                    style="background-color: #f4f4f4"
                    :src="li.write_base64"
                    alt="write-show"
                  />
                </span>
              </template>

              <template v-else-if="data.property.fill_type === fillTypeList[3].value">
                <SoundRecordBox
                  ref="record"
                  :key="j"
                  type="mini"
                  :many-times="false"
                  class="record-box"
                  :answer-record-list="data.audio_answer_list"
                  :task-model="isJudgingRightWrong ? 'ANSWER' : ''"
                  @handleWav="handleMiniWav($event, li.mark)"
                />
              </template>

              <span v-show="computedAnswerText(li.mark).length > 0" :key="`answer-${j}`" class="right-answer">
                {{ computedAnswerText(li.mark) }}
              </span>
            </template>
          </template>
        </p>
      </div>
      <SoundRecord
        v-if="isEnable(data.property.is_enable_voice_answer)"
        ref="record"
        type="normal"
        class="record-box"
        :answer-record-list="data.record_list"
        :task-model="isJudgingRightWrong ? 'ANSWER' : ''"
        @handleWav="handleWav"
      />
      <div v-if="showLang" class="lang">
        {{ data.multilingual.find((item) => item.type === getLang())?.translation }}
      </div>
    </div>

    <WriteDialog :visible.sync="writeVisible" @confirm="handleWriteConfirm" />
  </div>
</template>

<script>
import {
  getFillData,
  fillFontList,
  fillTypeList,
  arrangeTypeList,
  audioPositionList,
} from '@/views/book/courseware/data/fill';

import PreviewMixin from '../common/PreviewMixin';
import AudioFill from './components/AudioFillPlay.vue';
import SoundRecord from '../../common/SoundRecord.vue';
import SoundRecordBox from '@/views/book/courseware/preview/components/record_input/SoundRecord.vue';
import WriteDialog from './components/WriteDialog.vue';

export default {
  name: 'FillPreview',
  components: {
    AudioFill,
    SoundRecord,
    SoundRecordBox,
    WriteDialog,
  },
  mixins: [PreviewMixin],
  data() {
    return {
      data: getFillData(),
      fillTypeList,
      modelEssay: [],
      selectedWordList: [], // 用于存储选中的词汇
      writeVisible: false,
      writeMark: '',
    };
  },
  computed: {
    fontFamily() {
      return fillFontList.find(({ value }) => this.data.property.fill_font === value).font;
    },
  },
  watch: {
    'data.model_essay': {
      handler(list) {
        if (!list || !Array.isArray(list)) return;

        this.modelEssay = JSON.parse(JSON.stringify(list));
        this.answer.answer_list = list
          .map((item) => {
            return item
              .map(({ type, content, audio_answer_list, mark }) => {
                if (type === 'input') {
                  return {
                    value: content,
                    mark,
                    audio_answer_list,
                    write_base64: '',
                  };
                }
              })
              .filter((item) => item);
          })
          .flat();
      },
      deep: true,
      immediate: true,
    },
    modelEssay: {
      handler(list) {
        if (!list || !Array.isArray(list)) return;

        this.answer.answer_list = list
          .map((item) => {
            return item
              .map(({ type, content, audio_answer_list, mark }) => {
                if (type === 'input') {
                  return {
                    value: content,
                    mark,
                    audio_answer_list,
                    write_base64: '',
                  };
                }
              })
              .filter((item) => item);
          })
          .flat();
      },
      deep: true,
      immediate: true,
    },
    isJudgingRightWrong(val) {
      if (!val) return;

      this.answer.answer_list.forEach(({ mark, value }) => {
        this.modelEssay.forEach((item) => {
          item.forEach((li) => {
            if (li.mark === mark) {
              li.content = value;
            }
          });
        });
      });

      this.handleWav(this.answer.record_list);
    },
    'data.record_list'(val) {
      this.answer.record_list = val;
    },
  },
  methods: {
    handleWav(data) {
      this.data.record_list = data;
    },
    /**
     * 处理小音频录音
     * @param {Object} data 音频数据
     * @param {String} mark 选项标识
     */
    handleMiniWav(data, mark) {
      if (!data || !mark) return;
      for (const item of this.modelEssay) {
        const li = item.find((li) => li?.mark === mark);
        if (li) {
          this.$set(li, 'audio_answer_list', data);
          break;
        }
      }
    },
    /**
     * 处理选中词汇
     * @param {String} content 选中的词汇内容
     * @param {String} mark 选项标识
     * @param {Object} li 当前输入框对象
     */
    handleSelectWord(content, mark, li) {
      if (!content || !mark || !li) return;

      li.content = content;
      this.selectedWordList.push(mark);
    },
    /**
     * 处理书写区确认
     * @param {String} data 书写区数据
     */
    handleWriteConfirm(data) {
      if (!data) return;
      for (const item of this.modelEssay) {
        const li = item.find((li) => li?.mark === this.writeMark);
        if (li) {
          this.$set(li, 'write_base64', data);
          break;
        }
      }
    },
    handleWriteClick(mark) {
      this.writeVisible = true;
      this.writeMark = mark;
    },
    getMainStyle() {
      const isRow = this.data.property.arrange_type === arrangeTypeList[0].value;
      const isFront = this.data.property.audio_position === audioPositionList[0].value;
      const isEnableVoice = this.data.property.is_enable_voice_answer === 'true';
      let _list = [
        { name: 'audio', value: '24px' },
        { name: 'fill', value: '1fr' },
      ];
      if (!isFront) {
        _list = _list.reverse();
      }
      let gridArea = '';
      let gridTemplateRows = '';
      let gridTemplateColumns = '';
      if (isRow) {
        gridArea = `"${_list[0].name} ${_list[1].name}${isEnableVoice ? ' record' : ''}" ${this.showLang ? ' "lang lang lang"' : ''}`;
        gridTemplateRows = `auto ${this.showLang ? 'auto' : ''}`;
        gridTemplateColumns = `${_list[0].value} ${_list[1].value}${isEnableVoice ? ' 160px' : ''}`;
      } else {
        gridArea = `"${_list[0].name}" "${_list[1].name}" ${isEnableVoice ? `" record" ` : ''} ${this.showLang ? ' "lang"' : ''}`;
        gridTemplateRows = `${_list[0].value} ${_list[1].value} ${isEnableVoice ? ' 32px' : ''} ${this.showLang ? 'auto' : ''}`;
        gridTemplateColumns = '1fr';
      }

      let style = {
        'grid-auto-flow': isRow ? 'column' : 'row',
        'column-gap': isRow ? '16px' : undefined,
        'row-gap': isRow ? undefined : '8px',
        'grid-template-areas': gridArea,
        'grid-template-rows': gridTemplateRows,
        'grid-template-columns': gridTemplateColumns,
      };
      return style;
    },
    /**
     * 计算答题对错选项字体颜色
     * @param {string} mark 选项标识
     */
    computedAnswerClass(mark) {
      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
        return '';
      }
      let selectOption = this.answer.answer_list.find((item) => item.mark === mark);
      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark);
      if (!selectOption) return '';
      let selectValue = selectOption.value;
      let answerValue = answerOption.value;
      let answerType = answerOption.type;
      let classList = [];
      let isRight =
        answerType === 'only_one' ? selectValue === answerValue : answerValue.split('/').includes(selectValue);
      if (this.isJudgingRightWrong) {
        isRight ? classList.push('right') : classList.push('wrong');
      }

      if (this.isShowRightAnswer && !isRight) {
        classList.push('show-right-answer');
      }
      return classList;
    },
    /**
     * 计算正确答案文本
     * @param {string} mark 选项标识
     */
    computedAnswerText(mark) {
      if (!this.isShowRightAnswer) return '';
      let selectOption = this.answer.answer_list.find((item) => item.mark === mark);
      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark);
      if (!selectOption) return '';
      let selectValue = selectOption.value;
      let answerValue = answerOption.value;
      let isRight = selectValue === answerValue;
      if (isRight) return '';
      return `（${answerValue}）`;
    },
  },
};
</script>

<style lang="scss" scoped>
@use '@/styles/mixin.scss' as *;

.select-preview {
  @include preview-base;

  .main {
    display: grid;
    align-items: center;
  }

  .fill-wrapper {
    grid-area: fill;
    font-size: 16pt;

    p {
      margin: 0;
    }

    .content {
      display: inline-block;
    }

    .record-box {
      display: inline-flex;
      align-items: center;
      background-color: #fff;
      border-bottom: 1px solid $font-color;
    }

    .write-click {
      display: inline-block;
      width: 104px;
      height: 32px;
      padding: 0 4px;
      vertical-align: bottom;
      cursor: pointer;
      border-bottom: 1px solid $font-color;

      img {
        width: 100%;
        height: 100%;
      }
    }

    .el-input {
      display: inline-flex;
      align-items: center;
      width: 120px;
      margin: 0 2px;

      &.pinyin :deep input.el-input__inner {
        font-family: 'PINYIN-B', sans-serif;
      }

      &.chinese :deep input.el-input__inner {
        font-family: 'arial', sans-serif;
      }

      &.english :deep input.el-input__inner {
        font-family: 'arial', sans-serif;
      }

      &.right {
        :deep input.el-input__inner {
          color: $right-color;
        }
      }

      &.wrong {
        :deep input.el-input__inner {
          color: $error-color;
        }
      }

      & + .right-answer {
        position: relative;
        left: -4px;
        display: inline-block;
        height: 32px;
        line-height: 28px;
        vertical-align: bottom;
        border-bottom: 1px solid $font-color;
      }

      :deep input.el-input__inner {
        padding: 0;
        font-size: 16pt;
        color: $font-color;
        text-align: center;
        background-color: #fff;
        border-width: 0;
        border-bottom: 1px solid $font-color;
        border-radius: 0;
      }
    }
  }

  .record-box {
    padding: 6px 12px;
    background-color: $fill-color;

    :deep .record-time {
      width: 100px;
    }
  }
}
</style>

<style lang="scss" scoped>
.word-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;

  .word-item {
    cursor: pointer;
  }
}
</style>
