import React, { Component } from "react";
import { Button } from "antd";
import { WeaLocaleProvider } from "ecCom";
import { Controlled as CodeMirror } from "react-codemirror2";
import { keyboardBaseBtns } from "./constants";
import CodeAction from "./components/codeAction";
import cs from "classnames";
import "./index.less";
import "codemirror/lib/codemirror.css";
import "codemirror/lib/codemirror.js";
import "codemirror/mode/javascript/javascript.js";

require("./extendCodeMirror");
const getLabel = WeaLocaleProvider.getLabel;

class ExcelEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: "",
      isFormter: false,
      isCustomFunctionClick: false
    };
    this.editorRef = null;
    this.timer = null;
  }

  componentWillReceiveProps(nextProps, nextContext) {
    if (nextProps.value !== this.props.value && nextProps.value) this.setState({ value: nextProps.value });
  }

  componentWillUnmount() {
    if (this.timer) clearInterval(this.timer);
    this.setState({ isCustomFunctionClick: false });
  }

  autoFormatSelection = () => {
    const { isFormter } = this.state;
    if (isFormter) {
      const script_length = this.editorRef.getValue().length;
      const startPos = { line: 0, ch: 0, sticky: null };
      const endPos = this.editorRef.doc.posFromIndex(script_length);
      this.editorRef.setSelection(startPos, endPos);
      this.editorRef.autoFormatRange(startPos, endPos);
      this.editorRef.commentRange(true, startPos, endPos);
    } else {
      this.editorRef.undo();
      // this.editorRef.undo();
    }
  };
  insertText = text => {
    const cursor = this.editorRef.getCursor();
    this.editorRef.replaceRange(text, cursor);
    this.editorRef.refresh();
    this.editorRef.focus();
  };
  replaceToWidget = (editor) => {
    editor.getAllMarks().forEach(m => m.clear());
  };
  handleVariSelect = str => this.insertText(`{${str}}`);
  handleFuncSelect = str => {
    const cursor = this.editorRef.getCursor();
    this.editorRef.replaceRange(`${str}()`, cursor);
    this.timer = setTimeout(() => {
      const { line, ch } = this.editorRef.getCursor();
      this.editorRef.setCursor({ line, ch: ch - 1 });
      this.editorRef.refresh();
      this.editorRef.focus();
    }, 100);
  };
  handleEditorRedo = () => {
    const { ch, line } = this.editorRef.getCursor();
    const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
    const codeValue = this.editorRef.getValue();
    if (delStr === "}") {
      if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
        this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
      } else {
        this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") }, { line, ch });
      }
    } else {
      this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
    }
    this.editorRef.refresh();
    this.editorRef.focus();
  };
  handleBackSpaceRedo = () => {
    const { ch, line } = this.editorRef.getCursor();
    const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
    const codeValue = this.editorRef.getValue();
    if (delStr === "}") {
      if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
        this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
      } else {
        this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") + 1 }, { line, ch });
      }
    }
    this.editorRef.refresh();
    this.editorRef.focus();
  };

  render() {
    const { isFormter, isCustomFunctionClick } = this.state;
    const { groupParams = {}, isCustomFunction, value, onChangeCustomFunction } = this.props;
    const { referenceType } = groupParams;
    return (
      <React.Fragment>
        <div className="excel-codeWrap">
          <div className="excel-codeBox">
            <CodeMirror
              editorDidMount={editor => this.editorRef = editor}
              value={this.state.value}
              onBeforeChange={(editor, data, value) => {
                this.setState({ value }, () => this.props.onChange(this.state.value));
              }}
              onChange={(editor, data, value) => {
                this.replaceToWidget(editor, data, value);
              }}
              options={{
                lineNumbers: false,
                mode: "javascript",
                autofocus: false,
                styleActiveLine: true,
                lineWrapping: true,
                matchBrackets: true,
                lint: false,
                indentUnit: 2,
                cursorHeight: 0.85,
                placeholder: "",
                showCursorWhenSelecting: true
              }}
              onKeyDown={(_, { keyCode }) => keyCode === 8 && this.handleBackSpaceRedo()}
            />
          </div>
          {
            referenceType !== "sql" &&
            <div className="excel-codeBox-keyboard">
              <div className="excel-codeBox-keyboard-operate">
                <div className="excel-codeBox-keyboard-operate-content">
                  {
                    _.map(keyboardBaseBtns, item => {
                      const { key, label } = item;
                      return <Button
                        key={key} title={label} size="small"
                        className={cs(key === " " ? "excel-codeBox-keyboard-space" : "excel-codeBox-keyboard-base")}
                        onClick={() => this.insertText(key)}
                      >{label}</Button>;
                    })
                  }
                </div>
                <div className="excel-codeBox-keyboard-operate-clear">
                  <Button title="←" size="small" className="excel-codeBox-keyboard-del"
                          onClick={this.handleEditorRedo}>←</Button>
                  <Button title="C" size="small" className="excel-codeBox-keyboard-clear"
                          onClick={() => this.setState({ value: "", isCustomFunctionClick: true })}>C</Button>
                </div>
              </div>
              <Button type="ghost"
                      onClick={() => this.setState({ isFormter: !isFormter }, () => this.autoFormatSelection())}>
                {!isFormter ? getLabel(111, "格式美化") : getLabel(111, "格式还原")}
              </Button>
            </div>
          }
        </div>
        {/*公式参数列表*/}
        <CodeAction groupParams={groupParams} isCustomFunction={isCustomFunction} onVariSelect={this.handleVariSelect}
                    onFuncSelect={this.handleFuncSelect} codeVal={value} isCustomFunctionClick={isCustomFunctionClick}
                    onChangeCustomFunction={onChangeCustomFunction}
        />
      </React.Fragment>
    );
  }
}

export default ExcelEditor;
