<template>
  <ModuleBase :type="data.type">
    <template #content>
      <!-- eslint-disable max-len -->
      <div class="fill-wrapper">
        <RichText
          v-model="data.content"
          :is-fill="true"
          toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright"
          :wordlimit-num="false"
        />
        <el-input
          v-if="data.property.fill_type === fillTypeList[1].value"
          v-model="data.vocabulary"
          type="textarea"
          :autosize="{ minRows: 2, maxRows: 4 }"
          resize="none"
          placeholder="请输入词汇，用于选词填空"
        />

        <span class="tips">在需要加空的内容处插入 3 个或以上的下划线“_”。</span>
        <div v-if="data.audio_file_id">
          <SoundRecord :wav-blob.sync="data.audio_file_id" />
        </div>
        <template v-else>
          <div :class="['upload-audio-play']">
            <UploadAudio
              v-if="data.property.audio_generation_method === 'upload'"
              :file-id="data.audio_file_id"
              :show-upload="!data.audio_file_id"
              @upload="uploads"
              @deleteFile="deleteFiles"
            />
            <div v-else-if="data.property.audio_generation_method === 'auto'" class="auto-matic" @click="handleMatic">
              <SvgIcon icon-class="voiceprint-line" class="record" />
              <span class="auto-btn">{{ data.audio_file_id ? '已生成' : '生成音频' }}</span
              >{{ data.audio_file_id ? '成功' : '' }}
            </div>
            <SoundRecord v-else :wav-blob.sync="data.audio_file_id" />
          </div>
        </template>
        <el-button @click="identifyText">识别</el-button>
        <div class="correct-answer">
          <el-input
            v-for="(item, i) in data.answer.answer_list.filter(({ type }) => type === 'any_one')"
            :key="item.mark"
            v-model="item.value"
            @blur="handleTone(item.value, i)"
          >
            <span slot="prefix">{{ i + 1 }}.</span>
          </el-input>
        </div>
      </div>
    </template>
  </ModuleBase>
</template>

<script>
import ModuleMixin from '../../common/ModuleMixin';
import SoundRecord from '@/views/book/courseware/create/components/question/fill/components/SoundRecord.vue';
import UploadAudio from '@/views/book/courseware/create/components/question/fill/components/UploadAudio.vue';

import { getFillData, arrangeTypeList, fillFontList, fillTypeList } from '@/views/book/courseware/data/fill';
import { addTone, handleToneValue } from '@/views/book/courseware/data/common';
import { getRandomNumber } from '@/utils';
import { GetStaticResources } from '@/api/app';

export default {
  name: 'FillPage',
  components: {
    SoundRecord,
    UploadAudio,
  },
  mixins: [ModuleMixin],
  data() {
    return {
      data: getFillData(),
      fillTypeList,
    };
  },
  watch: {
    'data.property.arrange_type': 'handleMindMap',
    'data.property.fill_font': 'handleMindMap',
    'data.vocabulary': {
      handler(val) {
        if (!val) return;
        this.data.word_list = val
          .split(/[\n\r]+/)
          .map((item) => item.split(' ').filter((s) => s))
          .flat()
          .map((content) => {
            return {
              content,
              mark: getRandomNumber(),
            };
          });
      },
    },
  },
  methods: {
    // 识别文本
    identifyText() {
      this.data.model_essay = [];
      this.data.answer.answer_list = [];

      this.data.content
        .split(/<(p|div)[^>]*>(.*?)<\/(p|div)>/g)
        .filter((s) => s && !s.match(/^(p|div)$/))
        .forEach((item) => {
          if (item.charCodeAt() === 10) return;
          let str = item
            // 去除所有的 font-size 样式
            .replace(/font-size:\s*\d+(\.\d+)?px;/gi, '')
            // 匹配 class 名为 rich-fill 的 span 标签和三个以上的_，并将它们组成数组
            .replace(/<span class="rich-fill".*?>(.*?)<\/span>|([_]{3,})/gi, '###$1$2###');
          this.data.model_essay.push(this.splitRichText(str));
        });
    },
    // 分割富文本
    splitRichText(str) {
      let _str = str;
      let start = 0;
      let index = 0;
      let arr = [];
      let matchNum = 0;
      while (index !== -1) {
        index = _str.indexOf('###', start);
        if (index === -1) break;
        matchNum += 1;
        arr.push({ content: _str.slice(start, index), type: 'text' });
        if (matchNum % 2 === 0 && arr.length > 0) {
          arr[arr.length - 1].type = 'input';
          arr[arr.length - 1].audio_answer_list = [];
          let mark = getRandomNumber();
          arr[arr.length - 1].mark = mark;
          let content = arr[arr.length - 1].content;
          // 设置答案数组
          let isUnderline = /^_{3,}$/.test(content);
          this.data.answer.answer_list.push({
            value: isUnderline ? '' : content,
            mark,
            type: isUnderline ? 'any_one' : 'only_one',
          });

          // 将 content 设置为空，为预览准备
          arr[arr.length - 1].content = '';
        }
        start = index + 3;
      }
      let last = _str.slice(start);
      if (last) {
        arr.push({ content: last, type: 'text' });
      }
      return arr;
    },
    handleTone(value, i) {
      if (!/^[a-zA-Z0-9\s]+$/.test(value)) return;
      this.data.answer.answer_list[i].value = value
        .trim()
        .split(/\s+/)
        .map((item) => {
          return handleToneValue(item);
        })
        .map((item) =>
          item.map(({ number, con }) => (number && con ? addTone(Number(number), con) : number || con || '')),
        )
        .filter((item) => item.length > 0)
        .join(' ');
    },
    uploads(file_id) {
      this.data.audio_file_id = file_id;
    },
    deleteFiles() {
      this.data.audio_file_id = '';
    },
    // 自动生成音频
    handleMatic() {
      GetStaticResources('tool-TextToVoiceFile', {
        text: this.data.content.replace(/<[^>]+>/g, ''),
      })
        .then(({ status, file_id }) => {
          if (status === 1) {
            this.data.audio_file_id = file_id;
          }
        })
        .catch(() => {});
    },
    /**
     * @description 处理思维导图数据
     */
    handleMindMap() {
      const { fill_font, arrange_type } = this.data.property;
      const fontLabel = fillFontList.find((item) => item.value === fill_font)?.label || '';
      const arrangeLabel = arrangeTypeList.find((item) => item.value === arrange_type)?.label || '';
      this.data.mind_map.node_list = [
        {
          name: `${arrangeLabel}${fontLabel}填空组件`,
        },
      ];
    },
  },
};
</script>

<style lang="scss" scoped>
.fill-wrapper {
  display: flex;
  flex-direction: column;
  row-gap: 16px;
  align-items: flex-start;

  :deep .rich-wrapper {
    width: 100%;
  }

  .tips {
    font-size: 12px;
    color: #999;
  }

  .auto-matic,
  .upload-audio-play {
    :deep .upload-wrapper {
      margin-top: 0;
    }

    .audio-wrapper {
      :deep .audio-play {
        width: 16px;
        height: 16px;
        color: #000;
        background-color: initial;
      }

      :deep .audio-play.not-url {
        color: #a1a1a1;
      }

      :deep .voice-play {
        width: 16px;
        height: 16px;
      }
    }
  }

  .auto-matic {
    display: flex;
    flex-shrink: 0;
    column-gap: 12px;
    align-items: center;
    width: 200px;
    padding: 5px 12px;
    background-color: $fill-color;
    border-radius: 2px;

    .auto-btn {
      font-size: 16px;
      font-weight: 400;
      line-height: 22px;
      color: #1d2129;
      cursor: pointer;
    }
  }

  .correct-answer {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    .el-input {
      width: 180px;

      :deep &__prefix {
        display: flex;
        align-items: center;
        color: $text-color;
      }
    }
  }
}
</style>
