<template>
  <ModuleBase ref="base" :type="data.type">
    <template #content>
      <div v-loading="loading">
        <ul class="option-list">
          <li v-for="(li, i) in data.option_list" :key="i" class="option-item">
            <div v-for="(item, j) in li" :key="item.mark" class="option">
              <span class="serial-number">{{ computeOptionNumber(i, data.property.serial_number_type_list[j]) }}</span>
              <span class="option-content">
                <RichText
                  v-if="property.isGetContent"
                  ref="richText"
                  v-model="item.content"
                  placeholder="请输入"
                  :inline="true"
                  :height="32"
                  :font-size="data?.unified_attrib?.font_size"
                  :font-family="data?.unified_attrib?.font"
                  :font-color="data?.unified_attrib?.text_color"
                  :is-view-pinyin="isEnable(data.property.view_pinyin)"
                  @createParsedTextInfoPinyin="handleParsedTextPinyin($event, i, j)"
                />
              </span>
              <span class="multilingual" @click="openMultilingual(i, j)">
                <SvgIcon icon-class="multilingual" class-name="multilingual" width="12" height="12" />
              </span>
            </div>
          </li>
        </ul>
        <div class="answer-tips">答案：</div>
        <ul class="answer-list">
          <li v-for="(li, i) in data.answer.answer_list" :key="i" class="answer-item">
            <template v-for="(item, j) in li">
              <span v-if="j === 0" :key="`zero-${j}-${item.mark}`">{{ answerList[j][i].label }}</span>
              <el-select
                v-if="j === 1 || j === 2"
                :key="`select-${j}`"
                v-model="item.mark"
                multiple
                placeholder="请选择"
              >
                <el-option
                  v-for="answer in answerList[j]"
                  :key="answer.value"
                  :label="answer.label"
                  :value="answer.value"
                />
              </el-select>
              <span v-if="j === 1 && data.property.column_num === 3" :key="`one-${j}-${item.mark}`">
                {{ answerList[j][i].label }}
              </span>
            </template>
          </li>
        </ul>

        <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">
          <span>拼音效果</span>
          <el-button
            v-show="isEnable(data.property.view_pinyin)"
            type="text"
            icon="el-icon-refresh"
            title="刷新"
            class="refresh-pinyin-btn"
            @click.native="handleViewPinyin(true)"
          />
        </el-divider>
        <div v-show="isEnable(data.property.view_pinyin)" class="proofread-table-wrapper">
          <table class="proofread-table">
            <tbody>
              <template v-for="(row, i) in data.option_list">
                <tr v-for="(item, j) in row" :key="item.mark">
                  <td class="pinyin-cell">
                    <PinyinText
                      ref="PinyinText"
                      :paragraph-list="item.paragraph_list"
                      :rich-text-list="item.rich_text_list"
                      :pinyin-position="data.property.pinyin_position"
                      @fillCorrectPinyin="fillCorrectPinyin($event, i, j)"
                    />
                  </td>
                  <td class="proofread-cell">
                    <WordProofread
                      button-text="分词校对"
                      :word-data="getOptionWordData(item)"
                      @save="saveOptionWord($event, i, j)"
                    />
                  </td>
                </tr>
              </template>
            </tbody>
          </table>
        </div>
      </div>

      <MultilingualFill
        v-if="curSelectRow !== -1 && curSelectColumn !== -1"
        :visible.sync="multilingualVisible"
        :text="data.option_list[curSelectRow][curSelectColumn].content"
        :translations="data.option_list[curSelectRow][curSelectColumn].multilingual"
        @SubmitTranslation="handleMultilingualTranslation"
      />

      <AnswerAnalysisList
        v-if="data.answer_list?.length > 0 || data.analysis_list?.length > 0"
        :answer-list="data.answer_list"
        :analysis-list="data.analysis_list"
        :unified-attrib="data.unified_attrib"
        @updateAnswerAnalysisFileList="updateAnswerAnalysisFileList"
        @deleteAnswerAnalysis="deleteAnswerAnalysis"
      />
    </template>
  </ModuleBase>
</template>

<script>
import ModuleMixin from '../../common/ModuleMixin';
import PinyinText from '@/components/PinyinText.vue';
import WordProofread from '@/views/book/courseware/create/components/common/WordProofread.vue';
import { buildWordProofreadData } from '@/views/book/courseware/create/components/common/wordProofread';

import { getMatchingData, getOption, getOptionItem } from '@/views/book/courseware/data/matching';
import { computeOptionMethods, serialNumberTypeList, computeOptionNumber } from '@/views/book/courseware/data/common';

export default {
  name: 'MatchingPage',
  components: {
    PinyinText,
    WordProofread,
  },
  mixins: [ModuleMixin],
  data() {
    return {
      data: getMatchingData(),
      computeOptionMethods,
      serialNumberTypeList,
      computeOptionNumber,
      curSelectRow: -1,
      curSelectColumn: -1,
      optionWordDataMap: {},
      optionWordDataSourceMap: {},
      loading: false,
      inited: false,
      // 用于记录 data.option_list 中 content 的签名
      optionContentSignature: '',
    };
  },
  computed: {
    answerList() {
      let list = Array.from({ length: this.data.property.column_num }, () => []);
      for (let i = 0; i < this.data.option_list.length; i++) {
        for (let j = 0; j < this.data.option_list[i].length; j++) {
          list[j].push({
            label: computeOptionMethods[this.data.property.serial_number_type_list[j]](i),
            value: this.data.option_list[i][j].mark,
          });
        }
      }
      return list;
    },
  },
  watch: {
    'data.property.column_num': [
      {
        handler(val) {
          let optionNum = this.data.option_list[0].length;
          if (val > optionNum) {
            // 修改序号类型列表
            this.data.property.serial_number_type_list.push(
              serialNumberTypeList[val]?.value || serialNumberTypeList[0].value,
            );
            // 增加选项
            for (let i = 0; i < this.data.option_list.length; i++) {
              this.data.option_list[i].push(getOptionItem());
            }
            // 修改答案列表
            this.data.answer.answer_list.forEach((li) => {
              li.push({ mark: [] });
            });
            return;
          }
          if (val < optionNum) {
            this.data.property.serial_number_type_list.splice(-1, 1);
            this.data.option_list.forEach((li) => {
              li.splice(-1, 1);
            });
            // 修改答案列表
            this.data.answer.answer_list.forEach((li) => {
              li.splice(-1, 1);
            });
          }
        },
      },
      'handlerMindMap',
    ],
    'data.property.row_num': [
      {
        handler(val) {
          let optionNum = this.data.option_list.length;
          if (val > optionNum) {
            for (let i = 0; i < val - optionNum; i++) {
              this.data.option_list.push(getOption(this.data.property.column_num));
            }
            // 增加答案列表
            this.data.answer.answer_list.push(
              Array.from({ length: this.data.property.column_num }, () => ({ mark: [] })),
            );
            // 将答案列表最后一项的第一个元素设置进答案列表第一项
            this.data.answer.answer_list[this.data.answer.answer_list.length - 1][0] = {
              mark: this.data.option_list[this.data.option_list.length - 1][0].mark,
            };
            return;
          }
          if (val < optionNum) {
            this.data.option_list.splice(val);
            this.data.answer.answer_list.splice(val);
          }
        },
      },
      'handlerMindMap',
    ],
    'data.option_list': {
      handler(newVal) {
        if (this.loading) return;
        if (this.inited || !Array.isArray(newVal) || newVal.length <= 0) return;
        if (!this.isEnable(this.data.property.view_pinyin)) return;
        this.ensureOptionWordProofreadData();
        this.inited = true;
      },
      deep: true,
    },
    'data.property.view_pinyin': {
      handler(val) {
        if (this.property.isSilentPropertyWatch) return;
        if (!this.isEnable(val)) {
          this.data.option_list.forEach((row) => {
            row.forEach((item) => {
              item.paragraph_list = [];
              item.paragraph_list_parameter = {
                text: '',
                pinyin_proofread_word_list: [],
              };
            });
          });
          this.optionWordDataMap = {};
          this.optionWordDataSourceMap = {};
          return;
        }
        this.handleViewPinyin().finally(() => {
          this.inited = true;
        });
      },
      deep: true,
    },
  },
  methods: {
    ensureOptionWordProofreadData() {
      this.data.option_list.forEach((row) => {
        row.forEach((option) => {
          if (!option?.mark) return;
          const wordData = { detail: [{ sentences: [], segList: [] }] };
          option.rich_text_list?.forEach((item) => {
            const sentence = (item.word_list || []).reduce((acc, itemss) => `${acc + itemss.text}`, '');
            const seg = (item.word_list || []).map((itemss) => itemss.text);
            wordData.detail[0].sentences.push(sentence);
            wordData.detail[0].segList.push(seg);
          });
          this.$set(this.optionWordDataMap, option.mark, wordData);
          this.$set(this.optionWordDataSourceMap, option.mark, option.content);
        });
      });
    },
    async handleViewPinyin(isPrompt = false) {
      if (isPrompt) {
        try {
          await this.$confirm('刷新将会重置分词和拼音，是否刷新？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
          });
        } catch (e) {
          return;
        }
      }
      this.loading = true;
      try {
        if (!this.isEnable(this.data.property.view_pinyin)) {
          this.data.option_list.forEach((row) => {
            row.forEach((item) => {
              item.paragraph_list = [];
              item.paragraph_list_parameter = {
                text: '',
                pinyin_proofread_word_list: [],
              };
            });
          });
          this.optionWordDataMap = {};
          this.optionWordDataSourceMap = {};
          return;
        }

        const tasks = [];
        this.data.option_list.forEach((row, i) => {
          row.forEach((item, j) => {
            const text = item.content;
            if (!text) return;
            item.paragraph_list_parameter.text = text;
            tasks.push(
              this.createParsedTextInfoPinyin(text, i, j).then(({ parsed_text }) => {
                this.$set(this.optionWordDataMap, item.mark, buildWordProofreadData(parsed_text?.paragraph_list || []));
                this.$set(this.optionWordDataSourceMap, item.mark, text);
              }),
            );
          });
        });
        await Promise.all(tasks);
      } finally {
        this.loading = false;
      }
    },
    getOptionWordData(option) {
      if (!option || !option.mark) return { detail: [] };
      return this.optionWordDataMap[option.mark] || { detail: [] };
    },
    async saveOptionWord(saveArr, rowIndex, colIndex) {
      const option = this.data.option_list[rowIndex]?.[colIndex];
      if (!option) return;
      const { parsed_text } = await this.createParsedTextInfoPinyin(
        option.content,
        rowIndex,
        colIndex,
        'option_list',
        saveArr,
      );
      this.$set(this.optionWordDataMap, option.mark, buildWordProofreadData(parsed_text?.paragraph_list || []));
      this.$set(this.optionWordDataSourceMap, option.mark, option.content || '');
    },
    /**
     * @description 处理思维导图
     */
    handlerMindMap() {
      this.data.mind_map.node_list = [
        { name: `${this.data.property.row_num}行${this.data.property.column_num}列连线组件` },
      ];
    },
    openMultilingual(i, j) {
      this.curSelectRow = i;
      this.curSelectColumn = j;
      this.$nextTick(() => {
        this.multilingualVisible = true;
      });
    },
    handleMultilingualTranslation(translations) {
      this.$set(this.data.option_list[this.curSelectRow][this.curSelectColumn], 'multilingual', translations);
      this.curSelectColumn = -1;
      this.curSelectRow = -1;
    },
    handleParsedTextPinyin(text, i, j) {
      if (!this.isEnable(this.data.property.view_pinyin)) return;
      if (this.data.option_list?.length > 0 && this.data.option_list[0].paragraph_list?.length > 0) return;
      if (!text) return;
      this.data.option_list[i][j].paragraph_list_parameter.text = text.replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ');
      this.createParsedTextInfoPinyin(text, i, j);
    },
  },
};
</script>

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

.option-list {
  display: flex;
  flex-direction: column;
  row-gap: 16px;

  .option-item {
    display: flex;
    column-gap: 16px;

    .option {
      display: flex;
      flex: 1;
      column-gap: 4px;
      align-items: center;

      .serial-number {
        @include serial-number(32px);
      }

      .option-content {
        flex: 1;
        padding: 0 4px;
        margin-left: 4px;
        background-color: $fill-color;
      }

      .multilingual {
        margin-left: 2px;
        line-height: 12px;
        cursor: pointer;
      }
    }
  }
}

.answer-tips {
  margin: 16px 0;
}

.answer-list {
  display: flex;
  flex-direction: column;
  row-gap: 16px;

  .answer-item {
    display: flex;
    column-gap: 16px;
    align-items: center;

    span {
      display: inline-block;
      height: 32px;
      padding: 4px 8px;
      color: #c9cdd4;
      background-color: $fill-color;
    }

    .el-select {
      flex: 1;
    }
  }
}

.proofread-table-wrapper {
  margin-top: 8px;
}

.proofread-table {
  width: 100%;
  border-collapse: collapse;

  td {
    padding: 8px;
    vertical-align: top;
    border: 1px solid #ebeef5;
  }

  .pinyin-cell {
    width: calc(100% - 140px);
  }

  .proofread-cell {
    width: 140px;
    text-align: center;
    white-space: nowrap;
  }
}
</style>
