"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];

Object.defineProperty(exports, "__esModule", {
  value: true
});
Object.defineProperty(exports, "ThemeSwitch", {
  enumerable: true,
  get: function get() {
    return _enum.ThemeSwitch;
  }
});
exports["default"] = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));

var _tslib = require("tslib");

var _react = _interopRequireDefault(require("react"));

var _reactDom = require("react-dom");

var _componentClasses = _interopRequireDefault(require("component-classes"));

var _classnames = _interopRequireDefault(require("classnames"));

var _mobx = require("mobx");

var _mobxReact = require("mobx-react");

var _defaultTo = _interopRequireDefault(require("lodash/defaultTo"));

var _isString = _interopRequireDefault(require("lodash/isString"));

var _isEqual = _interopRequireDefault(require("lodash/isEqual"));

var _noop = _interopRequireDefault(require("lodash/noop"));

var _KeyCode = _interopRequireDefault(require("../../../lib/_util/KeyCode"));

var _icon = _interopRequireDefault(require("../../../lib/icon"));

var _FormField2 = require("../field/FormField");

var _enum = require("./enum");

var _autobind = _interopRequireDefault(require("../_util/autobind"));

var _enum2 = require("../form/enum");

var _switch = _interopRequireDefault(require("../switch"));

var CodeMirror;

if (typeof window !== 'undefined') {
  // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
  CodeMirror = require('react-codemirror2').Controlled;
}

var defaultCodeMirrorOptions = {
  theme: 'idea',
  lineNumbers: true,
  lint: true,
  gutters: ['CodeMirror-lint-markers']
};

var CodeArea = /*#__PURE__*/function (_FormField) {
  (0, _inherits2["default"])(CodeArea, _FormField);

  var _super = (0, _createSuper2["default"])(CodeArea);

  function CodeArea(props, content) {
    var _this;

    (0, _classCallCheck2["default"])(this, CodeArea);
    _this = _super.call(this, props, content);
    _this.cmOptions = _this.getCodeMirrorOptions();

    _this.handleThemeChange = function (value) {
      _this.setTheme(value ? _enum.ThemeSwitch.idea : _enum.ThemeSwitch.material);
    };

    _this.getHeader = function () {
      var _classNames;

      var _this$props = _this.props,
          title = _this$props.title,
          options = _this$props.options,
          themeSwitch = _this$props.themeSwitch;

      if (!title && (options && options.theme || !themeSwitch)) {
        return null;
      }

      var titleNode = title ? /*#__PURE__*/_react["default"].createElement("div", {
        className: "".concat(_this.prefixCls, "-header-title")
      }, title) : null;
      var themeSwitchNode = (!options || !options.theme) && themeSwitch ? /*#__PURE__*/_react["default"].createElement("div", {
        className: "".concat(_this.prefixCls, "-header-switch")
      }, /*#__PURE__*/_react["default"].createElement(_switch["default"], {
        unCheckedChildren: /*#__PURE__*/_react["default"].createElement(_icon["default"], {
          type: "moon-circle"
        }),
        defaultChecked: _this.theme !== _enum.ThemeSwitch.material,
        onChange: _this.handleThemeChange
      }, /*#__PURE__*/_react["default"].createElement(_icon["default"], {
        type: "wb_sunny"
      }))) : null;
      var headerClassNames = (0, _classnames["default"])("".concat(_this.prefixCls, "-header"), (_classNames = {}, (0, _defineProperty2["default"])(_classNames, "".concat(_this.prefixCls, "-header-light"), _this.theme !== _enum.ThemeSwitch.material), (0, _defineProperty2["default"])(_classNames, "".concat(_this.prefixCls, "-header-dark"), _this.theme === _enum.ThemeSwitch.material), _classNames));
      return /*#__PURE__*/_react["default"].createElement("div", {
        className: headerClassNames
      }, titleNode, themeSwitchNode);
    };
    /**
     * 编辑器失去焦点时，调用父类方法，同步DataSet中的内容
     *
     * @memberof CodeArea
     */


    _this.handleCodeMirrorBlur = (0, _mobx.action)(function (codeMirrorInstance) {
      var formatter = _this.props.formatter; // 更新DataSet的值之前，先去拿到原始的raw格式

      var value = codeMirrorInstance.getValue();

      if (formatter) {
        var getRaw = formatter.getRaw,
            getFormatted = formatter.getFormatted;
        value = getRaw(getFormatted(value));
      }

      _this.midText = value;

      _this.setValue(value);

      _this.isFocused = false;
      _this.isFocus = false;
      var element = _this.wrapper || (0, _reactDom.findDOMNode)((0, _assertThisInitialized2["default"])(_this));

      if (element) {
        (0, _componentClasses["default"])(element).remove("".concat(_this.prefixCls, "-focused"));
      }
    });
    /**
     * 在CodeMirror编辑器实例挂载前添加额外配置
     *
     * @memberof CodeArea
     */

    _this.handleCodeMirrorDidMount = function (editor, value, cb) {
      var _this$props2 = _this.props,
          formatter = _this$props2.formatter,
          style = _this$props2.style,
          formatHotKey = _this$props2.formatHotKey,
          unFormatHotKey = _this$props2.unFormatHotKey,
          editorDidMount = _this$props2.editorDidMount;

      var _ref = style || {},
          _ref$width = _ref.width,
          width = _ref$width === void 0 ? '100%' : _ref$width,
          _ref$height = _ref.height,
          height = _ref$height === void 0 ? 100 : _ref$height;

      var options = {
        Tab: function Tab(cm) {
          if (cm.somethingSelected()) {
            cm.indentSelection('add'); // 有选中内容时整体缩进
          } else {
            // 使用空格代替缩进
            var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
            cm.replaceSelection(spaces);
          }
        }
      };

      if (formatter) {
        if (formatHotKey) {
          // default: 'Alt-F'
          options[formatHotKey] = function (cm) {
            return cm.setValue(formatter.getFormatted(cm.getValue()));
          };
        }

        if (unFormatHotKey) {
          // default: 'Alt-R'
          options[unFormatHotKey] = function (cm) {
            return cm.setValue(formatter.getRaw(cm.getValue()));
          };
        }
      }

      editor.setSize(width, height); // default size: ('100%', 100)

      editor.setOption('extraKeys', options);

      if (editorDidMount) {
        editorDidMount(editor, value, cb);
      }

      if (_this.labelLayout === _enum2.LabelLayout["float"]) {
        var display = editor.display;

        if (display) {
          var gutters = display.gutters;

          if (gutters) {
            var offsetWidth = gutters.offsetWidth;

            if (offsetWidth !== _this.floatLabelOffsetX) {
              (0, _mobx.runInAction)(function () {
                _this.floatLabelOffsetX = offsetWidth;
              });
            }
          }
        }
      }
    };

    var options = props.options;
    var theme = options && options.theme ? options.theme : props.themeSwitch;

    _this.setTheme((0, _defaultTo["default"])(theme, defaultCodeMirrorOptions.theme));

    _this.disposer = (0, _mobx.autorun)(function () {
      // 在绑定dataSet的情况下
      // 当手动修改过codeArea里面的值以后 再使用record.set去更新值 组件不会更新
      // 原因在于此时 this.text 不为 undefined 因此 getTextNode 的计算值不会进行改变 导致组件不重新渲染
      // 其他的组件会对 this.text 在blur的时候进行undefined的修改 但是这个组件不能这么做
      // 原因在于 record 中的值为 raw的非格式化数据 blur后因为进行了一次record数据的修改 所以再次重新那数据必然导致
      // 当数据存在错误的时候  codeArea去格式化 因为格式化失败了
      // 当数据不存在存在错误的时候即使特地将其去格式化也依旧会被格式化
      var formatter = props.formatter;

      var recordValue = _this.getValue();

      var value = formatter ? formatter.getFormatted(recordValue) : recordValue; // 分别监听 受控 及 DataSet 进行管理时值的变化

      if (recordValue !== _this.midText || _this.dataSet && _this.name) {
        _this.setText(value);
      }
    });
    return _this;
  }

  (0, _createClass2["default"])(CodeArea, [{
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.disposer();
    }
  }, {
    key: "handleBeforeChange",
    value: function handleBeforeChange(_editor, _data, value) {
      this.setText(value);
    }
  }, {
    key: "handleCodeMirrorKeyDown",
    value: function handleCodeMirrorKeyDown(cm, e) {
      var _this$props3 = this.props,
          _this$props3$onKeyDow = _this$props3.onKeyDown,
          onKeyDown = _this$props3$onKeyDow === void 0 ? _noop["default"] : _this$props3$onKeyDow,
          _this$props3$onEnterD = _this$props3.onEnterDown,
          onEnterDown = _this$props3$onEnterD === void 0 ? _noop["default"] : _this$props3$onEnterD;

      switch (e.keyCode) {
        case _KeyCode["default"].ENTER:
          onEnterDown(e);
          break;

        case _KeyCode["default"].ESC:
          cm.getInputField().blur();
          break;

        default:
      }

      onKeyDown(e);
    }
  }, {
    key: "getCodeMirrorOptions",
    value: function getCodeMirrorOptions() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props.options;
      return (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, defaultCodeMirrorOptions), options);
    }
  }, {
    key: "getOmitPropsKeys",
    value: function getOmitPropsKeys() {
      return (0, _get2["default"])((0, _getPrototypeOf2["default"])(CodeArea.prototype), "getOmitPropsKeys", this).call(this).concat(['formatHotKey', 'unFormatHotKey', 'editorDidMount']);
    }
  }, {
    key: "getOtherProps",
    value: function getOtherProps() {
      var otherProps = (0, _get2["default"])((0, _getPrototypeOf2["default"])(CodeArea.prototype), "getOtherProps", this).call(this);
      delete otherProps.onChange;
      otherProps.onKeyDown = this.handleCodeMirrorKeyDown;
      otherProps.className = this.getOtherClassName(otherProps);
      return otherProps;
    }
  }, {
    key: "getOtherClassName",
    value: function getOtherClassName(otherProps) {
      return (0, _classnames["default"])(otherProps.className, (0, _defineProperty2["default"])({}, "".concat(this.prefixCls, "-dark"), this.theme === _enum.ThemeSwitch.material));
    }
  }, {
    key: "setThemeWrapper",
    value: function setThemeWrapper(nextProps) {
      var options = nextProps.options,
          themeSwitch = nextProps.themeSwitch;
      var _this$props4 = this.props,
          preOptions = _this$props4.options,
          preThemeSwitch = _this$props4.themeSwitch;
      var preOptionsTheme = preOptions && preOptions.theme;
      var optionsTheme = options && options.theme;

      if (preOptionsTheme !== optionsTheme || preThemeSwitch !== themeSwitch) {
        this.setTheme((0, _defaultTo["default"])(optionsTheme || themeSwitch, defaultCodeMirrorOptions.theme));
      }
    }
  }, {
    key: "componentWillReceiveProps",
    value: function componentWillReceiveProps(nextProps, nextContext) {
      var options = nextProps.options;

      if (!(0, _isEqual["default"])(options, this.props.options)) {
        this.cmOptions = this.getCodeMirrorOptions(options);
      }

      this.setThemeWrapper(nextProps);
      (0, _get2["default"])((0, _getPrototypeOf2["default"])(CodeArea.prototype), "componentWillReceiveProps", this).call(this, nextProps, nextContext);
    }
  }, {
    key: "elementReference",
    value: function elementReference(node) {
      if (node && node.ref) {
        this.element = node.ref;
      }
    }
  }, {
    key: "renderWrapper",
    value: function renderWrapper() {
      if (CodeMirror) {
        this.cmOptions.readOnly = this.disabled ? 'nocursor' : this.readOnly;
        this.cmOptions.theme = this.theme;
        var text = this.getTextNode();
        var header = this.getHeader();
        return /*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({}, this.getWrapperProps()), header, /*#__PURE__*/_react["default"].createElement("label", null, /*#__PURE__*/_react["default"].createElement(CodeMirror, (0, _extends2["default"])({}, this.getOtherProps(), {
          value: (0, _isString["default"])(text) ? text : this.processValue(this.getValue()),
          options: this.cmOptions,
          onBeforeChange: this.handleBeforeChange,
          onBlur: this.handleCodeMirrorBlur,
          editorDidMount: this.handleCodeMirrorDidMount
        })), this.renderFloatLabel()));
      }
    }
  }, {
    key: "setTheme",
    value: function setTheme(theme) {
      if (theme !== this.theme) {
        this.theme = theme;
      }
    }
  }, {
    key: "setText",
    value: function setText(text) {
      this.text = text;
    }
  }, {
    key: "getTextNode",
    value: function getTextNode(value) {
      return this.text === undefined ? (0, _get2["default"])((0, _getPrototypeOf2["default"])(CodeArea.prototype), "getTextNode", this).call(this, value) || '' : this.text;
    }
  }, {
    key: "processValue",
    value: function processValue(value) {
      var text = (0, _get2["default"])((0, _getPrototypeOf2["default"])(CodeArea.prototype), "processValue", this).call(this, value);
      var formatter = this.props.formatter;
      return formatter && (0, _isString["default"])(text) ? formatter.getFormatted(text) : text;
    }
  }]);
  return CodeArea;
}(_FormField2.FormField);

CodeArea.displayName = 'CodeArea';
CodeArea.defaultProps = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, _FormField2.FormField.defaultProps), {}, {
  suffixCls: 'code-area',
  formatHotKey: 'Alt-F',
  unFormatHotKey: 'Alt-R'
});
(0, _tslib.__decorate)([_mobx.observable], CodeArea.prototype, "text", void 0);
(0, _tslib.__decorate)([_mobx.observable], CodeArea.prototype, "theme", void 0);
(0, _tslib.__decorate)([_autobind["default"]], CodeArea.prototype, "handleBeforeChange", null);
(0, _tslib.__decorate)([_autobind["default"]], CodeArea.prototype, "handleCodeMirrorKeyDown", null);
(0, _tslib.__decorate)([_autobind["default"]], CodeArea.prototype, "elementReference", null);
(0, _tslib.__decorate)([_mobx.action], CodeArea.prototype, "setTheme", null);
(0, _tslib.__decorate)([_mobx.action], CodeArea.prototype, "setText", null);
CodeArea = (0, _tslib.__decorate)([_mobxReact.observer], CodeArea);
var _default = CodeArea;
exports["default"] = _default;
//# sourceMappingURL=CodeArea.js.map
