import { FormControlProps, FormItem, getVariable } from 'amis';
import mammoth from 'mammoth/mammoth.browser';
import React from 'react';

@FormItem({
  test: /(^|\/)examimport$/,
  name: 'examimport',
})
export class ExamImportRenderer extends React.Component<
  FormControlProps,
  {
    exam: Array<any>;
    file: any;
  }
> {
  constructor(props: FormControlProps) {
    super(props);
    this.state = {
      exam: [],
      file: '',
    };
  }

  // word 文件解析方法
  parseWord(event: any, organization_id: any, category: any, onChange: any) {
    const reader = new FileReader();
    reader.onload = (e: any) => {
      const arrayBuffer = e.target.result;
      const options = {
        convertImage: mammoth.images.imgElement((image: any) => {
          return image.read().then((res: any) => {
            let file = new Blob([res], {
              type: image.contentType,
            });
            let formData = new FormData();
            formData.set('file', file);

            return this.props.env
              .fetcher({
                url: 'storage/v1/object/exam',
                method: 'post',
                dataType: 'form-data',
                data: formData,
              })
              .then((res) => {
                return {
                  src: res.data.data.value,
                };
              });
          });
        }),
        ignoreEmptyParagraphs: false,
      };

      mammoth
        .convertToHtml({ arrayBuffer: arrayBuffer }, options)
        .then((resultObject: any) => {
          let temp: any[] = [];
          let local: any[] = [];

          // 清除粗体、软回车，按空行或题号分割题目，并做 forEach 循环
          resultObject.value
            .replace(/<strong>|<\/strong>/g, '')
            .replace(/<br \/><\/p>/g, '</p>')
            .replace(/<br \/>/g, '</p><p>')
            .split(/<p>\s*<\/p>|(?<!^|<p>\s*<\/p>)<p>\d+/g)
            .forEach((item: any, q_index: any) => {
              if (item) {
                // 清除开头的 . 或 、
                if (!item.match(/^<p>/g)) {
                  item = item.replace(/^(\.|、)/g, '<p>');
                }

                // 建立当前题目的分割序列
                let split_series: any[] = [];

                if (item.search(/<p>答案：|<p>答案:/g) > 0) {
                  split_series.push({
                    pattern: /(<p>答案：|<p>答案:)/g,
                    num: item.search(/<p>答案：|<p>答案:/g),
                    dict: 'answer',
                  });
                }
                if (item.search(/<p>答案解析：|<p>答案解析:/g) > 0) {
                  split_series.push({
                    pattern: /(<p>答案解析：|<p>答案解析:)/g,
                    num: item.search(/<p>答案解析：|<p>答案解析:/g),
                    dict: 'analysis',
                  });
                }
                if (item.search(/<p>难易程度：|<p>难易程度:/g) > 0) {
                  split_series.push({
                    pattern: /(<p>难易程度：|<p>难易程度:)/g,
                    num: item.search(/<p>难易程度：|<p>难易程度:/g),
                    dict: 'difficulty',
                  });
                }
                if (item.search(/<p>题型：|<p>题型:/g) > 0) {
                  split_series.push({
                    pattern: /(<p>题型：|<p>题型:)/g,
                    num: item.search(/<p>题型：|<p>题型:/g),
                    dict: 'type',
                  });
                }

                // 按分割序列各项在题目中的位置排序，从前到后
                split_series = split_series.sort((a, b) => a.num - b.num);

                let exam = item;
                let data_item: any = {};
                let last_split_item: any = {};

                // 按分割序列逐项分割当前题目
                split_series.forEach((split_item, index) => {
                  let result = exam.split(split_item.pattern);

                  // 如果是第一项，必定是题干和选项(如有)，其他项则为其他信息
                  if (!index) {
                    // 提取选项
                    let options = result[0].match(
                      /<p>[A-Za-z](\.|、).+?<\/p>(?=<p>[A-Za-z](\.|、)|$)/g
                    );

                    // 如果有选项则继续分割题干和选项，否则即为题干
                    if (options) {
                      let title = result[0]
                        .replace(/\n/g, '')
                        .match(/^.+?(?=<p>[A-Za-z](\.|、))/g)[0]
                        .replace(
                          /(<p>\d+(\.|、)\{<\/p>)|(?<=<p>)\d+(\.|、)|(<p>}<\/p>)/g,
                          ''
                        )
                        .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');

                      options = options.map((item: any) => {
                        return {
                          key: item.match(/(?<=<p>)[A-Za-z]/g)[0],
                          label: '<p>'
                            .concat(
                              item
                                .match(/(?<=\.|、).+<\/p>/g)[0]
                                .replace(/(<p>{<\/p>)|(<p>}<\/p>)/g, '')
                            )
                            .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, ''),
                          is_fixed: false,
                        };
                      });

                      // 判断是否有相同的选项
                      let key_set = new Set();
                      let key_count = 0;
                      options.forEach((item: any) => {
                        key_set.add(item.key);
                        key_count++;
                      });
                      if (key_set.size !== key_count) local.push(q_index + 1);

                      data_item.options = options;
                      data_item.title = title;
                    } else {
                      let title = result[0]
                        .replace(
                          /(<p>\d+(\.|、)\{<\/p>)|(?<=<p>)\d+(\.|、)|(<p>}<\/p>)/g,
                          ''
                        )
                        .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');

                      data_item.title = title;
                    }
                  } else {
                    // 清除 { 、} 和 分割项
                    data_item[last_split_item.dict] = result[0]
                      .replace(/(<p>{<\/p>)|(<p>}<\/p>)/g, '')
                      .replace(last_split_item.pattern, '<p>')
                      .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');

                    // 如果是答案、题型、难易程度，则清除 DOM 标签，并清除空格
                    if (
                      last_split_item.dict === 'answer' ||
                      last_split_item.dict === 'type' ||
                      last_split_item.dict === 'difficulty'
                    ) {
                      data_item[last_split_item.dict] = data_item[
                        last_split_item.dict
                      ]
                        .replace(/<p>|<\/p>/g, '')
                        .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');
                    }
                  }

                  // 最后一项
                  if (index + 1 === split_series.length) {
                    data_item[split_item.dict] = result[1]
                      .concat(result[2])
                      .replace(/(<p>{<\/p>)|(<p>}<\/p>)/g, '')
                      .replace(split_item.pattern, '<p>')
                      .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');

                    // 如果是答案、题型、难易程度，则清除 DOM 标签，并清除空格
                    if (
                      split_item.dict === 'answer' ||
                      split_item.dict === 'type' ||
                      split_item.dict === 'difficulty'
                    ) {
                      data_item[split_item.dict] = data_item[split_item.dict]
                        .replace(/<p>|<\/p>/g, '')
                        .replace(/(?<=<p>)\s+|\s+(?=<\/p>)/g, '');
                    }
                  }

                  // 重组分割项和剩余项
                  exam = result[1].concat(result[2]);

                  // 保留上一次分割的分割项
                  last_split_item = split_item;
                });

                if (data_item.type === '判断题') {
                  data_item.options = [
                    { key: '正确', label: '正确', is_fixed: false },
                    { key: '错误', label: '错误', is_fixed: false },
                  ];
                }

                data_item.organization_id = organization_id;
                data_item.category = category;
                temp.push(data_item);
              }
            });
          this.setState({ exam: temp, file: '' });
          if (!local.length) {
            onChange(this.state.exam);
          } else {
            this.props.env.notify(
              'error',
              `第 ${local.toString()} 题中有重复选项，请修改后重新上传`
            );
          }
        });
    };
    if (event.target.files.length !== 0) {
      reader.readAsArrayBuffer(event.target.files[0]);
    }
  }

  updateValue(event: any) {
    this.setState({ file: event.target.value });
  }

  render() {
    const { data, onChange } = this.props;
    const { exam } = this.state;
    const organization_id = getVariable(data, 'centre_id');
    const category = getVariable(data, 'tree');
    return (
      <form action="">
        <input
          type="file"
          accept=".docx"
          value={this.state.file}
          onChange={(event) => {
            this.parseWord(event, organization_id, category, onChange);
            this.updateValue(event);
          }}
        />
      </form>
    );
  }
}
