<!-- eslint-disable vue/no-v-html -->
<template>
  <div class="dialogue-preview">
    <div class="stem">
      <span class="question-number">{{ data.property.question_number }}.</span>
      <span v-html="sanitizeHTML(data.stem)"></span>
    </div>
    <div
      v-if="isEnable(data.property.is_enable_description)"
      class="description rich-text"
      v-html="sanitizeHTML(data.description)"
    ></div>

    <div class="content">
      <div v-for="(item, i) in optionList" :key="i" class="option-list">
        <span
          class="avatar"
          :style="{ backgroundColor: data.property.role_list.find(({ mark }) => mark === item.role).color }"
        >
          {{ data.property.role_list.find(({ mark }) => mark === item.role).name }}
        </span>

        <div v-if="item.type === 'text'" class="text-wrapper">
          <div class="text">
            <template v-for="(li, j) in item.content_list">
              <span v-if="li.type === 'text'" :key="j">{{ li.content }}</span>
              <template v-else-if="li.type === 'input'">
                <el-input
                  :key="j"
                  v-model="li.content"
                  :disabled="disabled"
                  :class="[...computedAnswerClass(li.mark, li.content)]"
                  :style="[{ width: Math.max(80, li.content.length * 16) + 'px' }]"
                />
                <span
                  v-show="computedAnswerText(li.mark, li.content).length > 0"
                  :key="`answer-${j}`"
                  class="right-answer"
                >
                  {{ computedAnswerText(li.mark, li.content) }}
                </span>
              </template>
            </template>
          </div>
          <SoundRecordPreview
            v-if="
              isEnable(data.property.is_enable_voice_answer) && item.content_list.some(({ type }) => type === 'input')
            "
            :wav-blob.sync="item.file_id"
            :disabled="disabled"
            type="small"
          />
        </div>

        <div v-else-if="item.type === 'image'" class="image">
          <img :src="file_map_list[item.file_id]" />
        </div>

        <div v-else-if="item.type === 'audio'" class="audio">
          <AudioPlay
            :file-id="item.file_id"
            :show-slider="true"
            :show-progress="false"
            :background-color="data.property.role_list.find(({ mark }) => mark === item.role).color"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import PreviewMixin from './components/PreviewMixin';
import SoundRecordPreview from './components/common/SoundRecordPreview.vue';

import { GetFileURLMap } from '@/api/app';

export default {
  name: 'DialoguePreview',
  components: {
    SoundRecordPreview,
  },
  mixins: [PreviewMixin],
  data() {
    return {
      optionList: [],
      file_map_list: [],
    };
  },
  watch: {
    'data.option_list': {
      handler(val) {
        let list = JSON.parse(JSON.stringify(val));
        let file_id_list = [];
        list.forEach(({ type, file_id }) => {
          if (type === 'image' || type === 'audio') {
            file_id_list.push(file_id);
          }
        });
        GetFileURLMap({ file_id_list }).then(({ url_map }) => {
          this.file_map_list = url_map;
        });
        this.optionList = list;
      },
      deep: true,
      immediate: true,
    },
    optionList: {
      handler(val) {
        this.answer.answer_list = [];
        val.forEach(({ type, content_list, mark, file_id }) => {
          if (type !== 'text') return;
          let list = content_list
            .map(({ type, mark, content }) => {
              if (type !== 'input') return;
              return {
                mark,
                content,
              };
            })
            .filter((item) => item);
          if (list.length <= 0) return;
          this.answer.answer_list.push({
            content_list: list,
            file_id,
            mark,
          });
        });
      },
      deep: true,
      immediate: true,
    },
    isJudgingRightWrong(val) {
      if (!val) return;
      this.answer.answer_list.forEach(({ mark, file_id, content_list }) => {
        let find = this.optionList.find((item) => item.mark === mark);
        find.file_id = file_id;
        find.content_list.forEach((item) => {
          if (item.type === 'text') return;
          let find = content_list.find((li) => li.mark === item.mark);
          item.content = find.content;
        });
      });
    },
  },
  methods: {
    /**
     * 计算答题对错选项字体颜色
     * @param {string} mark 选项标识
     * @param {string} content 选项内容
     */
    computedAnswerClass(mark, content) {
      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
        return '';
      }
      let rightValue = this.data.answer.answer_list.find((item) => item.mark === mark)?.value || '';
      let classList = [];
      let isRight = rightValue === content;

      if (this.isJudgingRightWrong) {
        isRight ? classList.push('right') : classList.push('wrong');
      }

      if (this.isShowRightAnswer && !isRight) {
        classList.push('show-right-answer');
      }
      return classList;
    },
    computedAnswerText(mark, content) {
      if (!this.isShowRightAnswer) return '';
      if (content.length === 0) return '';
      let find = this.data.answer.answer_list.find((item) => item.mark === mark);
      if (find.value === content) return '';
      if (!find) return '';
      return `（${find.value}）`;
    },
  },
};
</script>

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

.dialogue-preview {
  @include preview;

  .content {
    display: flex;
    flex-direction: column;
    row-gap: 16px;
    padding: 24px;
    background-color: $fill-color;
    border-radius: 16px;

    .option-list {
      display: flex;
      column-gap: 8px;

      .avatar {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        min-width: 40px;
        height: 40px;
        min-height: 40px;
        margin-right: 8px;
        font-size: 12px;
        color: #fff;
        border-radius: 50%;
      }

      .text-wrapper {
        display: flex;
        flex-direction: column;
        row-gap: 8px;
        align-items: flex-start;

        .text {
          padding: 8px 12px;
          font-size: 16px;
          word-break: break-all;
          background-color: #fff;
          border-radius: 8px;

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

            &.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;
              font-size: 16px;
              line-height: 28px;
              vertical-align: bottom;
              border-bottom: 1px solid $font-color;
            }

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

        .sound-record-preview {
          padding: 4px;
          background-color: #fff;
          border-radius: 40px;

          :deep .sound-item .sound-item-span {
            color: #1d1d1d;
            background-color: #fff;
          }

          :deep .sound-item-luyin .sound-item-span {
            color: #fff;
            background-color: $light-main-color;
          }
        }
      }

      .image img {
        border-radius: 8px;
      }
    }
  }
}
</style>
