import React, { Component } from "react";
import E from "wangeditor";
import { message } from "antd";
import UploadOss from "@/core/upload";
import "./QuestionEditor.less";
const MEDIA_MAP = [
  {
    title: "音频",
    icon: <React.Fragment>&#xe756;</React.Fragment>,
    key: "VOICE",
  },
  {
    title: "录音",
    icon: <React.Fragment>&#xe7bb;</React.Fragment>,
    key: "AUDIO",
  },
  {
    title: "图片",
    icon: <React.Fragment>&#xe758;</React.Fragment>,
    key: "PICTURE",
  },
  {
    title: "视频",
    icon: <React.Fragment>&#xe755;</React.Fragment>,
    key: "VIDEO",
  },
];
class QuestionEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editorId: window.random_string(16),
      visiblePlacehold: true,
      visibleMediaBox: false,
      zIndex: 9,
      focusFlag: false,
      isShowSingleInput: true,
      contentLength: 0,
      isGapFilling: props.isGapFilling,
      contentType: props.contentType,
      detailInfo: props.detailInfo || {},
      blanksList: props.blanksList || [],
    };
  }
  componentDidMount() {
    const editorRoot = new E(
      `#editor${this.state.editorId}_tabbar`,
      `#editor${this.state.editorId}_content`
    );
    this.setState({ editorRoot }, () => {
      this.renderEditor(editorRoot);
      editorRoot.create();
      this.editorRoot = editorRoot;
    });
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    return {
      detailInfo: nextProps.detailInfo,
    };
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { detailInfo, blanksList } = nextProps;
    if (this.state.detailInfo !== detailInfo) {
      this.setState({ detailInfo: nextProps.detailInfo }, () => {
        this.renderEditor(this.state.editorRoot);
      });
    }
    if (blanksList !== this.state.blanksList) {
      this.setState({
        blanksList,
      });
    }
    return true;
  }

  handleUploadMedia = (key) => {
    this.props.onUploadMedia && this.props.onUploadMedia(key);
  };

  getBoxDom = () => {
    const { markKey } = this.props;
    const domList = document.getElementsByClassName(
      `question-edtior_box__${markKey}`
    );
    let zIndex = 99;
    _.find(domList, (domItem, domIndex) => {
      if (domItem.getAttribute("editorid") === this.state.editorId) {
        zIndex = zIndex + domList.length - domIndex;
        return domItem;
      }
    });
    return zIndex;
  };

  handleChangeContent = (content) => {
    content &&
      this.editorRoot.txt.html(
        /^\<p/.test(content) ? content : `<p>${content}</p>`
      );
  };

  renderEditor(editorRoot) {
    const { editorId, detailInfo } = this.state;
    const { onChange, bindChangeContent } = this.props;
    editorRoot.config.menus = [];
    editorRoot.config.uploadImgMaxSize = 1 * 1024 * 1024;
    editorRoot.config.customAlert = function (info) {
      message.warning(/1M/.test(info) ? "图片大于1M，请使用图片上传" : info);
    };
    editorRoot.config.customUploadImg = function (files, insert) {
      // files 是 input 中选中的文件列表
      // insert 是获取图片 url 后，插入到编辑器的方法
      UploadOss.uploadBlobToOSS(files[0], window.random_string(16)).then(
        (urlStr) => {
          insert(urlStr);
        }
      );
    };
    editorRoot.config.zIndex = 999;
    editorRoot.config.placeholder = "";
    editorRoot.config.pasteFilterStyle = true;
    editorRoot.config.pasteIgnoreImg = true;
    editorRoot.config.focus = false;
    // 自定义处理粘贴的文本内容
    editorRoot.config.pasteTextHandle = function (content) {
      if (content == "" && !content) return "";
      var str1 = content; // 所有特殊字符
      str1 = str1.replace(/<xml>[\s\S]*?<\/xml>/gi, "");
      str1 = str1.replace(/<style>[\s\S]*?<\/style>/gi, "");
      str1 = str1.replace(/<\/?[^>]*>/g, "");
      str1 = str1.replace(/[ | ]*\n/g, "\n");
      str1 = str1.replace(/\&nbsp\;/gi, " ");
      str1 = str1.replace(/[\r\n]/g, "");
      str1 = str1.replace(/<\/?a.*?>/g, "");
      var str2 = content; // 保留空格和换行的其他字符
      str2 = str2.replace(/<xml>[\s\S]*?<\/xml>/gi, "");
      str2 = str2.replace(/<style>[\s\S]*?<\/style>/gi, "");
      str2 = str2.replace(/<\/?a.*?>/g, "");
      if (editorRoot.txt.text().length + str1.length > 1000) {
        content = str2.substring(0, 1000);
        message.error("内容过长，不能超过1000字");
      } else {
        content = str2;
      }
      return content;
    };

    let prevList = [];

    let counter = 0;
    const isEdit = getParameterByName("id");
    if (isEdit) {
      const stemDom = document.getElementsByClassName("add-fill-line");
      prevList = [...stemDom].map((item) => item.id);
      localStorage.setItem("gap_ques_prevList", JSON.stringify(prevList));

      setTimeout(
        function () {
          const divHeight = document.getElementById(`editor${editorId}_content`)
            .firstChild.offsetHeight;
          if (divHeight > 30) {
            this.setState({ isShowSingleInput: false });
          } else {
            this.setState({ isShowSingleInput: true });
          }
        }.bind(this)
      );
    }

    editorRoot.config.onchange = (html) => {
      const conLen = html.replace(/<(?!img|input).*?>/g, "").length;
      counter++;
      const { focusFlag } = this.state;
      const textLength = editorRoot.txt.text().replace(/\&nbsp\;/gi, " ")
        .length;
      const imgLength = html.match(/<img/g)
        ? html.match(/<img/g).length * 2
        : 0;
      const contentLength = imgLength + textLength;
      const divHeight = document.getElementById(`editor${editorId}_content`)
        .firstChild.offsetHeight;
      if (divHeight > 30 || imgLength > 0) {
        this.setState({ isShowSingleInput: false });
      } else {
        this.setState({ isShowSingleInput: true });
      }
      if (
        this.state.isGapFilling &&
        this.state.contentType === "QUESTION_STEM"
      ) {
        const stemHtml = this.transferStemDocument(html);
        var _blanksList = stemHtml.getElementsByClassName("add-fill-line");
        const ids = [..._blanksList].map((item) => item.id);

        const isEdit = getParameterByName("id");
        if (isEdit && counter === 1) {
          const prev = localStorage.getItem("gap_ques_prevList");
          prevList = prev && JSON.parse(prev);
        }

        let idx = 0;
        if (prevList && ids) {
          idx = this.getNewArr(prevList, ids);
          const oldLen = prevList.length;
          idx = idx >= oldLen ? idx - oldLen : idx;
        }

        prevList = [...ids];

        this.setState({ blanksList: _blanksList }, () =>
          this.props.changeBlankCount(_blanksList, ids.length > 0 ? idx : -1)
        );
      }
      this.setState(
        {
          contentLength,
          visiblePlacehold:
            (conLen === 0 || (conLen === 1 && html === " ")) && !focusFlag,
        },
        () => {
          onChange && onChange(html, this.state.contentLength);
        }
      );
    };

    editorRoot.config.onblur = () => {
      this.setState({
        focusFlag: false,
        visibleMediaBox: false,
        zIndex: 9,
      });
    };

    const contentHtml = /^\<p/.test(detailInfo.content)
      ? detailInfo.content
      : `<p>${detailInfo.content}</p>`;
    editorRoot.txt.html(detailInfo.content);
    const textLength = editorRoot.txt.text().replace(/\&nbsp\;/gi, " ").length;
    const imgLength = contentHtml.match(/<img/g)
      ? contentHtml.match(/<img/g).length * 2
      : 0;
    const contentLength = imgLength + textLength;
    this.setState(
      {
        contentLength,
        visiblePlacehold: contentLength === 0 && !this.state.focusFlag,
      },
      () => {
        onChange && onChange(contentHtml, this.state.contentLength);
      }
    );
    bindChangeContent && bindChangeContent(this.handleChangeContent);
  }

  getNewArr(a, b) {
    const arr = [...a, ...b];
    const idx = arr.findIndex((item) => {
      return !(a.includes(item) && b.includes(item));
    });
    return idx;
  }

  transferStemDocument = (txt) => {
    const template = `<div class='option-content'>${txt}</div>`;
    let doc = new DOMParser().parseFromString(template, "text/html");
    let div = doc.querySelector(".option-content");
    return div;
  };

  insertBlank = (blanks) => {
    var blanks = `<input class="add-fill-line" disabled correctAnswerList="[]" id=${window.random_string(
      16
    )} value="填空"/>`;
    this.editorRoot.cmd.do("insertHTML", blanks);
    document.getSelection().collapseToEnd();
    var _blanksList = [];
    _blanksList = document.getElementsByClassName("add-fill-line");
    this.setState({ blanksList: _blanksList });
    this.props.changeBlankCount(_blanksList);
  };

  render() {
    const {
      editorId,
      visiblePlacehold,
      visibleMediaBox,
      zIndex,
      focusFlag,
      contentLength,
      isShowSingleInput,
      isGapFilling,
      contentType,
    } = this.state;
    const {
      placehold,
      mediaBtn = ["VOICE", "AUDIO", "PICTURE", "VIDEO"],
      limitLength = 1000,
      markKey,
    } = this.props;
    return (
      <div
        className={`question-edtior_box question-edtior_box__${markKey}`}
        editorid={editorId}
        style={{ zIndex }}
        onMouseEnter={() => {
          if (visibleMediaBox || focusFlag) return;
          const setZIndex = this.getBoxDom();
          this.setState({
            visibleMediaBox: true,
            zIndex: setZIndex,
          });
        }}
        onMouseLeave={() => {
          if (!visibleMediaBox || focusFlag) return;
          this.setState({
            visibleMediaBox: false,
            zIndex: 9,
          });
        }}
      >
        <div
          className="editor-box"
          id={`editor${editorId}_tabbar`}
          style={{ display: "none" }}
        ></div>
        <div
          className={
            isShowSingleInput ? "editor-box-single " : "editor-box-multiple"
          }
          style={{
            border:
              this.props.validateStatus === "error" ||
              contentLength > limitLength
                ? "1px solid red"
                : "",
          }}
        >
          <div
            className="editor-box editor-box_content"
            id={`editor${editorId}_content`}
          ></div>
          <div className="editor-limit">
            <span style={{ color: contentLength > limitLength ? "red" : "" }}>
              {contentLength}
            </span>
            /{limitLength}
          </div>
        </div>
        {isGapFilling && contentType === "QUESTION_STEM" && (
          <div className="editor-fill-info">
            在需要填写答案的地方
            <span
              className="editor-fill-info_icon icon iconfont"
              onClick={this.insertBlank}
            >
              &#xe83e; 插入占位符
            </span>
          </div>
        )}
        <div
          className={`editor-limit-tip${
            contentLength > limitLength ? " mt6" : ""
          }`}
          style={{ height: contentLength > limitLength ? 20 : 0 }}
        >
          最多只能输入1000字
        </div>
        {visiblePlacehold && (
          <div className="editor-placehold">{placehold}</div>
        )}
        {visibleMediaBox && !_.isEmpty(mediaBtn) && (
          <div
            className="edtior-media_box"
            style={{
              top:
                isGapFilling && contentType === "QUESTION_STEM"
                  ? "53%"
                  : "100%",
            }}
          >
            <div className="edtior-media_list">
              {_.map(mediaBtn, (mediaItem) => {
                const mediaBtnMap = _.find(
                  MEDIA_MAP,
                  (mapItem) => mapItem.key === mediaItem
                );
                return (
                  mediaBtnMap && (
                    <div
                      className="edtior-media_item"
                      key={mediaItem}
                      onClick={() => this.handleUploadMedia(mediaItem)}
                    >
                      <div className="edtior-media_item__icon icon iconfont">
                        {mediaBtnMap.icon}
                      </div>
                      <div className="edtior-media_item__name">
                        {mediaBtnMap.title}
                      </div>
                    </div>
                  )
                );
              })}
            </div>
          </div>
        )}
      </div>
    );
  }
}

export default QuestionEditor;
