<template>
  <QuestionBase>
    <template #content>
      <div v-show="isMask" class="mask"></div>
      <div class="stem">
        <RichText v-model="data.stem" :font-size="18" placeholder="输入题干" />

        <RichText
          v-if="isEnable(data.property.is_enable_description)"
          v-model="data.description"
          placeholder="输入提示"
        />
      </div>

      <div class="content">
        <div class="option-wrapper" :style="computedOptionStyle()">
          <template v-for="i in data.property.column_number">
            <div :key="i" class="fill-form">
              <!-- 头部 -->
              <span v-if="isEnable(data.property.is_enable_table_header)" class="form-header">
                <span v-if="isEnable(data.property.is_enable_number_column) && i === 1" class="serial-number"></span>
                <el-input v-model="data.option_header_list[i - 1].text" placeholder="请输入" />
              </span>

              <span v-for="j in data.property.row_number" :key="j" :class="['form-item', `form-item-${i}-${j}`]">
                <span v-if="i === 1 && isEnable(data.property.is_enable_number_column)" class="serial-number">
                  {{ j }}
                </span>
                <el-input
                  v-model="data.option_list[j - 1][i - 1].text"
                  placeholder="请输入"
                  type="textarea"
                  resize="none"
                  @blur="handleTone(data.option_list[j - 1][i - 1].text, i, j)"
                />
              </span>
            </div>
            <span
              v-if="i !== data.property.column_number"
              :key="`resize-${i}`"
              class="resize"
              @mousedown="resize($event, i)"
            ></span>
          </template>
        </div>

        <template v-if="isEnable(data.property.is_enable_reference_answer)">
          <span class="reference-title">参考答案：</span>
          <div class="form-wrapper">
            <div class="form" :style="{ width: `${data.property.form_width}px` }">
              <div v-if="isEnable(data.property.is_enable_table_header)" class="form-header">
                <div
                  v-for="(item, i) in data.reference_answer_option_header_list"
                  :key="i"
                  :style="{
                    borderLeft: isEnable(data.property.is_enable_number_column) || i > 0 ? '1px solid #e0e0e0' : 'none',
                    width:
                      isEnable(data.property.is_enable_number_column) && i === 0
                        ? `calc(${item.width}% - 39px)`
                        : `${item.width}%`,
                    marginLeft: isEnable(data.property.is_enable_number_column) && i === 0 ? '39px' : '0',
                  }"
                  class="header-item"
                >
                  <el-input v-model="item.text" placeholder="请输入" />
                </div>
              </div>
              <div v-for="(item, i) in data.reference_answer_option_list" :key="i" class="form-content">
                <div
                  v-for="(li, j) in item"
                  :key="li.mark"
                  :style="{ width: `${data.reference_answer_option_header_list[j].width}%` }"
                  class="form-item"
                >
                  <span v-if="j === 0 && isEnable(data.property.is_enable_number_column)" class="serial-number">
                    {{ i + 1 }}
                  </span>
                  <div class="item-content">
                    <el-input
                      v-model="li.text"
                      class="fill"
                      placeholder="请输入"
                      type="textarea"
                      resize="none"
                      @blur="handleTone(li.text, i, j, 'reference')"
                    />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </template>

        <div v-if="isEnable(data.property.is_enable_analysis)" class="analysis">
          <div class="analysis-title">解析：</div>
          <RichText v-model="data.analysis" :is-border="true" :font-size="14" placeholder="输入解析" />
        </div>
      </div>
    </template>

    <template #property>
      <el-form :model="data.property" label-width="72px" label-position="left">
        <el-form-item label="题号">
          <el-input v-model="data.property.question_number" />
        </el-form-item>
        <el-form-item>
          <el-radio
            v-for="{ value, label } in questionNumberTypeList"
            :key="value"
            v-model="data.other.question_number_type"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>

        <el-form-item label="题干题号">
          <el-select v-model="data.property.stem_question_number_font_size">
            <el-option v-for="item in fontSizeList" :key="item" :label="item" :value="item" />
          </el-select>
        </el-form-item>

        <el-form-item label="提示">
          <el-radio
            v-for="{ value, label } in switchOption"
            :key="value"
            v-model="data.property.is_enable_description"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>

        <el-form-item label="参考答案">
          <el-radio
            v-for="{ value, label } in switchOption"
            :key="value"
            v-model="data.property.is_enable_reference_answer"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>

        <el-form-item label="解析">
          <el-radio
            v-for="{ value, label } in switchOption"
            :key="value"
            v-model="data.property.is_enable_analysis"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>

        <el-form-item label="表头">
          <el-radio
            v-for="{ value, label } in switchOption"
            :key="value"
            v-model="data.property.is_enable_table_header"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>

        <el-form-item label="序号列">
          <el-radio
            v-for="{ value, label } in switchOption"
            :key="value"
            v-model="data.property.is_enable_number_column"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>
        <el-form-item label="列表宽度">
          <el-input-number v-model="data.property.form_width" :min="100" :max="3000" :step="100" />
        </el-form-item>
        <el-form-item label="行数">
          <el-input-number v-model="data.property.row_number" :min="1" :max="30" />
        </el-form-item>
        <el-form-item label="列数">
          <el-input-number v-model="data.property.column_number" :min="2" :max="5" />
        </el-form-item>
        <el-form-item label="分值">
          <el-radio
            v-for="{ value, label } in scoreTypeList"
            :key="value"
            v-model="data.property.score_type"
            :label="value"
          >
            {{ label }}
          </el-radio>
        </el-form-item>
        <el-form-item>
          <el-input-number
            v-model="data.property.score"
            :min="0"
            :step="data.property.score_type === scoreTypeList[0].value ? 1 : 0.1"
          />
        </el-form-item>
      </el-form>
    </template>
  </QuestionBase>
</template>

<script>
import QuestionMixin from '../common/QuestionMixin.js';

import { getRandomNumber } from '@/utils';
import {
  analysisRecognitionTableFillData,
  getTableFillData,
  getOption,
} from '@/views/exercise_questions/data/tableFill.js';
import { addTone, handleToneValue } from '@/views/exercise_questions/data/common';

export default {
  name: 'TableFillQuestion',
  mixins: [QuestionMixin],
  data() {
    return {
      isMask: false,
      data: getTableFillData(),
    };
  },
  computed: {
    optionList() {
      return JSON.parse(JSON.stringify(this.data.option_list));
    },
  },
  watch: {
    'data.property.row_number': {
      handler(val) {
        this.handleRowNumber(val, 'option');
        this.handleRowNumber(val, 'reference');
      },
      immediate: true,
    },
    'data.property.column_number': {
      handler(val) {
        this.handleColumnNumber(val, 'option');
        this.handleColumnNumber(val, 'reference');
      },
      immediate: true,
    },
    optionList: {
      handler(newVal, oldVal) {
        if (newVal.length === 0 || !oldVal) return;
        if (newVal.length !== oldVal.length || newVal[0].length !== oldVal[0].length) return;
        newVal.forEach((item, i) => {
          item.forEach((li, j) => {
            let newValue = newVal[i][j];
            let oldValue = oldVal[i][j];
            if (newValue.text === oldValue.text) return;
            this.$set(this.data.option_list[i][j], 'type', newValue.text.length > 0 ? 'text' : 'input');
          });
        });
      },
      immediate: true,
      deep: true,
    },
  },
  methods: {
    /**
     * 智能识别
     * @param {String} text 识别数据
     */
    recognition(text) {
      let arr = this.recognitionCommon(text, true);
      let obj = analysisRecognitionTableFillData(arr);
      this.recognitionCommonSetObj(obj);
    },
    /**
     *鼠标拖动更改列宽
     * @param {MouseEvent} e 鼠标事件
     * @param {number} i 选项列表的索引
     */
    resize(e, i) {
      let target = e.target;
      let startX = e.clientX;
      this.isMask = true;

      // 鼠标拖动事件
      document.onmousemove = (e) => {
        const endX = e.clientX;
        let list = this.data.option_header_list;
        // 计算拖动的距离与总宽度的比例
        let w = ((endX - startX) / this.data.property.form_width) * 100;
        // 限制最小宽度为10，最大宽度为总宽度-10
        list[i - 1].width = Math.min(Math.max(10, list[i - 1].width + w), list[i - 1].width + list[i].width - 10);
        list[i].width = Math.min(Math.max(10, list[i].width - w), list[i - 1].width + list[i].width - 10);

        let referenceList = this.data.reference_answer_option_header_list;
        referenceList[i - 1].width = Math.min(
          Math.max(10, referenceList[i - 1].width + w),
          referenceList[i - 1].width + referenceList[i].width - 10,
        );
        referenceList[i].width = Math.min(
          Math.max(10, referenceList[i].width - w),
          referenceList[i - 1].width + referenceList[i].width - 10,
        );

        startX = endX;
      };

      // 鼠标松开事件
      document.onmouseup = () => {
        this.isMask = false;
        document.onmousemove = null;
        document.onmouseup = null;
        target.releaseCapture && target.releaseCapture(); // 当不在需要继续获得鼠标消息就要应该调用 ReleaseCapture() 释放掉
      };
      target.setCapture && target.setCapture(); // 该函数在属于当前线程的指定窗口里设置鼠标捕获
      return false;
    },
    handleTone(value, i, j, type = 'option') {
      let option =
        type === 'reference' ? this.data.reference_answer_option_list[i][j] : this.data.option_list[j - 1][i - 1];
      let text = 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(' ');
      this.$set(option, 'text', text);
    },

    handleRowNumber(val, type = 'option') {
      let option = type === 'reference' ? this.data.reference_answer_option_list : this.data.option_list;
      if (val > option.length) {
        option.push(Array.from({ length: this.data.property.column_number }, () => getOption(type)));
      } else if (val < option.length) {
        option.pop();
      }
    },
    handleColumnNumber(val, type) {
      let header_list =
        type === 'reference' ? this.data.reference_answer_option_header_list : this.data.option_header_list;
      // 列数变化时，需要重新计算每列的宽度
      if (val > header_list.length) {
        let width = 0;
        header_list.forEach((item) => {
          // 平均分配宽度，最小宽度为10
          let w = Math.max((item.width / val) * header_list.length, 10);
          width += item.width - w;
          item.width = w;
        });
        header_list.push({ mark: getRandomNumber(), text: '', width });
      } else if (val < header_list.length) {
        let width = header_list[val].width;
        header_list.pop();
        header_list.forEach((item) => {
          item.width += width / val;
        });
      }

      let listName = type === 'reference' ? 'reference_answer_option_list' : 'option_list';
      this.data[listName] = this.data[listName].map((item) => {
        const arr = [];
        for (let i = 0; i < val; i++) {
          arr.push(item[i] || getOption(type));
        }
        return arr;
      });
    },
    // 计算选项样式
    computedOptionStyle() {
      let gridTemplateColumns = this.data.option_header_list.reduce((acc, { width }, i) => {
        if (i === this.data.option_header_list.length - 1) {
          return `${acc}${width}%`;
        }
        return `${acc}${width}% 2px `;
      }, '');

      return {
        gridTemplateColumns,
        width: `${this.data.property.form_width}px`,
      };
    },
  },
};
</script>

<style lang="scss" scoped>
$table-border: 1px solid #e0e0e0;

.mask {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  cursor: col-resize;
}

.content {
  display: flex;
  flex-direction: column;
  row-gap: 8px;
  width: calc(100vw - 645px);
  overflow: auto;

  .option-wrapper {
    display: grid;
    grid-auto-flow: column;
    border: $table-border;

    .fill-form {
      display: flex;
      flex-direction: column;

      .form-header {
        display: flex;
        align-items: center;
        height: 40px;
        background-color: #eaeffb;
        border-bottom: $table-border;

        .serial-number {
          width: 41px;
          min-width: 41px;
          height: 40px;
          color: #000;
          border-right: $table-border;
        }

        :deep .el-input__inner {
          font-size: 16px;
          font-weight: bold;
          color: $main-color;
          text-align: center;
          background-color: #eaeffb;
        }
      }

      .form-item {
        display: flex;
        height: 55px;
        border-bottom: $border;

        .serial-number {
          width: 40px;
          min-width: 40px;
          line-height: 55px;
          text-align: center;
        }

        .el-textarea {
          border-bottom-width: 0;

          :deep &__inner {
            height: 54px;
            padding-top: 14px;
            font-size: 16px;
            color: $font-color;
            text-align: left;
            background-color: #fff;
            border-bottom-width: 0;
            border-radius: 0;

            &:focus {
              border-color: #c0c4cc;
            }
          }
        }

        :deep .tox-editor-header {
          display: none;
        }
      }
    }

    .resize {
      width: 2px;
      height: 100%;
      cursor: col-resize;
      background-color: #e0e0e0;
      border-radius: 4px;
    }
  }

  .reference-title {
    font-size: 14px;
    color: #000;
  }

  .form-wrapper {
    .form {
      border: $table-border;

      &-header {
        display: flex;
        font-weight: bold;
        color: $main-color;
        background-color: #eaeffb;

        .header-item {
          min-height: 40px;
          padding: 8px 12px;
          font-size: 16px;
          text-align: center;

          :deep .el-input__inner {
            font-size: 16px;
            font-weight: bold;
            color: $main-color;
            text-align: center;
            background-color: #eaeffb;
          }
        }
      }

      &-header + .form-content {
        border-top: $table-border;
      }

      &-content:not(:last-child) {
        border-bottom: $table-border;
      }

      &-content {
        display: flex;

        .form-item:not(:first-child) {
          border-left: $table-border;
        }

        .form-item {
          display: flex;
          align-items: center;
          min-height: 48px;
          overflow: auto;

          .item-content {
            flex: 1;
            padding: 8px 12px;
          }

          .el-textarea.fill {
            display: inline-flex;
            align-items: center;
            margin: 0 2px;

            :deep .el-textarea__inner {
              padding: 0;
              font-size: 16px;
              color: $font-color;
              text-align: left;
              background-color: #fff;
              border-width: 0;
              border-radius: 0;

              &::placeholder {
                line-height: 42px;
              }
            }
          }
        }
      }

      .serial-number {
        display: flex;
        align-items: center;
        width: 40px;
        min-width: 40px;
        max-width: 40px;
        height: 100%;
        padding: 8px 12px;
        border-right: $table-border;
      }
    }
  }
}

.property {
  .el-input-number {
    width: 200px;
  }
}
</style>
