import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
var _excluded = ["style"],
    _excluded2 = ["style", "tagRenderer"];
import { __decorate } from "tslib";
import React, { cloneElement, Component, isValidElement } from 'react';
import { action, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import classNames from 'classnames';
import raf from 'raf';
import noop from 'lodash/noop';
import KeyCode from '../../../es/_util/KeyCode';
import { pxToRem } from '../../../es/_util/UnitConvertor';
import Row from '../../../es/row';
import Col from '../../../es/col';
import TableContext from './TableContext';
import { findCell, findIndexedSibling, findRow, getColumnKey, getEditorByColumnAndRecord, getEditorByField, isInCellEditor, isStickySupport } from './utils';
import { stopEvent } from '../_util/EventManager';
import { ShowHelp } from '../field/enum';
import autobind from '../_util/autobind';
import { ResizeType } from '../text-area/enum';
import transform from '../_util/transform';
import { LabelLayout, ShowValidation } from '../form/enum';

function isTextArea(editor) {
  return editor.type.__PRO_TEXTAREA;
}

function isHTMLElement(el) {
  return el;
}

function offset(node, topNode) {
  var initialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [node.offsetLeft, node.offsetTop];

  if (topNode) {
    var offsetParent = node.offsetParent;

    if (isHTMLElement(offsetParent)) {
      if (offsetParent === topNode) {
        return initialize;
      }

      return offset(offsetParent, topNode, [offsetParent.offsetLeft + initialize[0], offsetParent.offsetTop + initialize[1]]);
    }
  }

  return initialize;
}

var TableEditor = /*#__PURE__*/function (_Component) {
  _inherits(TableEditor, _Component);

  var _super = _createSuper(TableEditor);

  function TableEditor() {
    var _this;

    _classCallCheck(this, TableEditor);

    _this = _super.apply(this, arguments);
    _this.inTab = false;
    return _this;
  }

  _createClass(TableEditor, [{
    key: "lock",
    get: function get() {
      var column = this.props.column;
      return column.lock;
    }
  }, {
    key: "handleWindowResize",
    value: function handleWindowResize() {
      if (this.cellNode) {
        this.alignEditor();
      }
    }
    /**
     * 触发多行编辑器失焦切换编辑/只读模式
     * @param e
     */

  }, {
    key: "handleWindowClick",
    value: function handleWindowClick(e) {
      var prefixCls = this.context.prefixCls;

      if (e.target.className !== "".concat(prefixCls, "-content") && e.target.className !== "".concat(prefixCls, "-body")) {
        this.handleEditorBlur(e);
      }
    }
  }, {
    key: "connect",
    value: function connect() {
      var _this2 = this;

      this.disconnect();
      var tableStore = this.context.tableStore;
      var dataSet = tableStore.dataSet,
          virtual = tableStore.virtual;

      if (virtual) {
        this.reaction = reaction(function () {
          return [tableStore.virtualVisibleStartIndex, tableStore.virtualVisibleEndIndex];
        }, function () {
          var current = dataSet.current;

          if (current && findRow(tableStore, current)) {
            var cellNode = _this2.cellNode,
                keep = _this2.keep;

            if (cellNode || keep) {
              raf(function () {
                _this2.alignEditor(cellNode);

                if (keep) {
                  delete _this2.keep;
                }
              });
            }
          } else if (!_this2.keep) {
            _this2.hideEditor(true);
          }
        });
      } else {
        this.reaction = reaction(function () {
          return dataSet.current;
        }, function (r) {
          return r && _this2.cellNode ? raf(function () {
            return _this2.alignEditor();
          }) : _this2.hideEditor();
        });
      }
    }
  }, {
    key: "disconnect",
    value: function disconnect() {
      if (this.reaction) {
        this.reaction();
      }
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this3 = this;

      var name = this.props.column.name;

      if (name) {
        var tableStore = this.context.tableStore;
        var dataSet = tableStore.dataSet,
            currentEditRecord = tableStore.currentEditRecord,
            editors = tableStore.editors;
        var record = currentEditRecord || dataSet.current;
        var field = dataSet.getField(name);

        if (field && field.get('multiLine', record)) {
          window.addEventListener('click', this.handleWindowClick);
        }

        window.addEventListener('resize', this.handleWindowResize);

        if (tableStore.inlineEdit) {
          this.reaction = reaction(function () {
            return tableStore.currentEditRecord;
          }, function (r) {
            return r ? raf(function () {
              return _this3.alignEditor();
            }) : _this3.hideEditor();
          });
        }

        editors.set(name, this);
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var name = this.props.column.name;

      if (name) {
        var editors = this.context.tableStore.editors;
        editors["delete"](name);
        window.removeEventListener('resize', this.handleWindowResize);
        window.removeEventListener('click', this.handleWindowClick);
        this.disconnect();
      }
    }
  }, {
    key: "saveRef",
    value: function saveRef(node) {
      this.editor = node;
    }
  }, {
    key: "saveWrap",
    value: function saveWrap(node) {
      this.wrap = node;
      var _this$context$tableSt = this.context.tableStore,
          inlineEdit = _this$context$tableSt.inlineEdit,
          currentEditRecord = _this$context$tableSt.currentEditRecord;

      if (node && (!inlineEdit || currentEditRecord)) {
        this.alignEditor(this.cellNode);
      }
    }
  }, {
    key: "handleEditorKeyEnterDown",
    value: function handleEditorKeyEnterDown(e) {
      var tableStore = this.context.tableStore;
      var editorNextKeyEnterDown = tableStore.editorNextKeyEnterDown;

      if (!e.isDefaultPrevented() && editorNextKeyEnterDown) {
        this.showNextEditor(e.shiftKey);
      }
    } // copy the previous tr value to to this cell value

  }, {
    key: "handleKeyDownCTRLD",
    value: function handleKeyDownCTRLD(e) {
      e.preventDefault();
      var cellNode = this.cellNode,
          tableStore = this.context.tableStore;
      var name = this.props.column.name;
      var dataSet = tableStore.dataSet;

      if (cellNode && tableStore && dataSet) {
        var parentTdNode = cellNode.parentNode;

        if (parentTdNode) {
          var parentTrNode = parentTdNode.parentNode;

          if (parentTrNode) {
            var previousElementSibling = findIndexedSibling(parentTrNode, -1);

            if (previousElementSibling) {
              var index = previousElementSibling.dataset.index;
              var currentIndex = parentTrNode.dataset.index;

              if (index && currentIndex) {
                var record = dataSet.findRecordById(index);
                var currentRecord = dataSet.findRecordById(currentIndex);

                if (record && currentRecord && tableStore) {
                  var cloneRecordData = record.clone().toData() || {};
                  var dealCloneRecordData = {};

                  if (name) {
                    dealCloneRecordData[name] = cloneRecordData[name];
                    currentRecord.set(dealCloneRecordData);
                  }
                }
              }
            }
          }
        }
      }
    }
  }, {
    key: "handleKeyDownCTRLS",
    value: function handleKeyDownCTRLS(e) {
      e.preventDefault();
      var dataSet = this.context.tableStore.dataSet;
      dataSet.submit();
    }
  }, {
    key: "handleEditorKeyDown",
    value: function handleEditorKeyDown(e) {
      if (![KeyCode.ESC, KeyCode.TAB].includes(e.keyCode) || !e.isDefaultPrevented()) {
        var ctrlKey = e.ctrlKey || e.metaKey;
        var tableStore = this.context.tableStore;
        var keyboard = tableStore.keyboard;

        switch (e.keyCode) {
          case KeyCode.ESC:
            this.blur();
            break;

          case KeyCode.TAB:
            {
              this.inTab = true;
              var column = this.props.column;
              var cellNode = !isStickySupport() && column.lock ? findCell(tableStore, getColumnKey(column), undefined, undefined, true) : this.cellNode;

              if (cellNode && cellNode.parentElement) {
                cellNode.focus();
              } else {
                var tdNode = this.tdNode;

                if (tdNode) {
                  tdNode.focus();
                  this.hideEditor();
                }
              }

              break;
            }

          case KeyCode.PAGE_UP:
          case KeyCode.PAGE_DOWN:
            stopEvent(e);
            break;

          case KeyCode.D:
            if (ctrlKey === true && keyboard) this.handleKeyDownCTRLD(e);
            break;

          case KeyCode.S:
            if (ctrlKey === true && keyboard) this.handleKeyDownCTRLS(e);
            break;

          default:
        }
      }

      var editorProps = this.editorProps;

      if (editorProps) {
        var _editorProps$onKeyDow = editorProps.onKeyDown,
            onKeyDown = _editorProps$onKeyDow === void 0 ? noop : _editorProps$onKeyDow;
        onKeyDown(e);
      }
    }
  }, {
    key: "handleEditorBlur",
    value: function handleEditorBlur(e) {
      var editorProps = this.editorProps,
          inTab = this.inTab,
          inlineEdit = this.context.tableStore.inlineEdit;

      if (!inTab && !inlineEdit) {
        this.hideEditor();
      }

      if (editorProps) {
        var _editorProps$onBlur = editorProps.onBlur,
            onBlur = _editorProps$onBlur === void 0 ? noop : _editorProps$onBlur;
        onBlur(e);
      }
    }
    /**
     * 多行编辑切换编辑器阻止冒泡
     * @param e
     */

  }, {
    key: "handleEditorClick",
    value: function handleEditorClick(e) {
      var editorProps = this.editorProps;

      if (editorProps) {
        var _editorProps$onClick = editorProps.onClick,
            onClick = _editorProps$onClick === void 0 ? noop : _editorProps$onClick;
        onClick(e);
      }

      stopEvent(e);
    }
  }, {
    key: "handleEditorResize",
    value: function handleEditorResize(width, height, target) {
      var _this4 = this;

      var editorProps = this.editorProps,
          cellNode = this.cellNode;
      var name = this.props.column.name;

      if (editorProps) {
        var _this$context = this.context,
            tableStore = _this$context.tableStore,
            dataSet = _this$context.dataSet,
            inlineEdit = _this$context.inlineEdit,
            rowHeight = _this$context.rowHeight;
        var currentEditRecord = tableStore.currentEditRecord;
        var _editorProps$onResize = editorProps.onResize,
            onResize = _editorProps$onResize === void 0 ? noop : _editorProps$onResize;
        onResize(width, height, target);
        var current = currentEditRecord || dataSet.current;

        if (current && name && (rowHeight !== height || current.getState("__column_resize_height_".concat(name)) !== undefined)) {
          current.setState("__column_resize_height_".concat(name), height);
        }

        if (inlineEdit) {
          raf(function () {
            tableStore.editors.forEach(function (editor) {
              var editorCellNode = editor.cellNode;

              if (editorCellNode) {
                editor.alignEditor(editorCellNode, editor === _this4 ? height : undefined);
              }
            });
          });
        } else if (cellNode) {
          this.alignEditor(cellNode, height);
        }
      }
    }
  }, {
    key: "blur",
    value: function blur() {
      var editor = this.editor;

      if (editor && editor.blur) {
        editor.blur();
      }
    }
  }, {
    key: "focus",
    value: function focus() {
      var editor = this.editor;

      if (editor && editor.focus) {
        editor.focus();
      }
    }
  }, {
    key: "alignEditor",
    value: function alignEditor(cellNode, height) {
      var wrap = this.wrap,
          editor = this.editor;
      var tableStore = this.context.tableStore;

      if (!cellNode || !cellNode.offsetParent) {
        var column = this.props.column;
        cellNode = findCell(tableStore, getColumnKey(column), undefined, undefined, true);
      }

      if (!this.cellNode && !tableStore.inlineEdit) {
        this.connect();
      }

      this.cellNode = undefined;

      if (cellNode) {
        var _cellNode = cellNode,
            parentElement = _cellNode.parentElement;
        this.tdNode = parentElement;

        if (parentElement) {
          this.cellNode = cellNode;

          if (height === undefined) {
            var _cellNode2 = cellNode,
                offsetHeight = _cellNode2.offsetHeight;

            if (offsetHeight !== this.height) {
              this.height = offsetHeight;
            }
          } else {
            this.height = height;
          }

          if (!this.rendered) {
            this.rendered = true;
          } else if (wrap) {
            var _cellNode3 = cellNode,
                offsetWidth = _cellNode3.offsetWidth;

            var _offset = offset(cellNode, wrap.parentElement),
                _offset2 = _slicedToArray(_offset, 2),
                left = _offset2[0],
                top = _offset2[1];

            if (this.originalCssText === undefined) {
              this.originalCssText = wrap.style.cssText;
            }

            var width = pxToRem(offsetWidth, true);

            if (width !== this.width) {
              this.width = width;
            }

            wrap.style.cssText = "width:".concat(width, ";").concat(transform("translate(".concat(pxToRem(left, true), ", ").concat(pxToRem(top, true), ")")));

            if (editor && editor.forcePositionChanged) {
              editor.forcePositionChanged();
            }
          }
        }
      }
    }
  }, {
    key: "hideEditor",
    value: function hideEditor(keep) {
      this.inTab = false;

      if (keep) {
        this.keep = true;
      }

      if (this.cellNode) {
        var tableStore = this.context.tableStore;
        tableStore.hideEditor();
        var wrap = this.wrap;

        if (wrap) {
          if (this.originalCssText !== undefined) {
            wrap.style.cssText = "width:".concat(this.width, ";").concat(this.originalCssText);
            this.originalCssText = undefined;
          }
        }

        this.cellNode = undefined;

        if (!keep && !tableStore.inlineEdit) {
          this.disconnect();
        }
      }
    }
  }, {
    key: "showNextEditor",
    value: function showNextEditor(reserve) {
      var name = this.props.column.name;

      if (name) {
        this.blur();
        var tableStore = this.context.tableStore;

        if (tableStore.showNextEditor(name, reserve)) {
          this.alignEditor();
          this.focus();
        }
      }
    }
    /**
     * 渲染多行编辑单元格
     */

  }, {
    key: "renderMultiLineEditor",
    value: function renderMultiLineEditor() {
      var _this5 = this;

      var name = this.props.column.name;

      if (name) {
        var _this$context2 = this.context,
            prefixCls = _this$context2.prefixCls,
            dataSet = _this$context2.dataSet,
            inlineEdit = _this$context2.inlineEdit,
            rowHeight = _this$context2.rowHeight,
            currentEditRecord = _this$context2.tableStore.currentEditRecord;
        var record = currentEditRecord || dataSet.current;

        if (record) {
          var multiLineFields = [];
          var ref = true;
          dataSet.fields.forEach(function (dsField, fieldName) {
            var bind = dsField.get('bind', record);

            if (bind && bind.split('.')[0] === name) {
              var field = record.fields.get(fieldName) || dsField;
              var editor = getEditorByField(field, record);
              _this5.editorProps = editor.props;

              var _this5$editorProps = _this5.editorProps,
                  _this5$editorProps$st = _this5$editorProps.style,
                  style = _this5$editorProps$st === void 0 ? {} : _this5$editorProps$st,
                  otherProps = _objectWithoutProperties(_this5$editorProps, _excluded);

              if (rowHeight !== 'auto') {
                style.height = pxToRem(rowHeight);
              }

              var newEditorProps = _objectSpread(_objectSpread({}, otherProps), {}, {
                style: style,
                ref: ref ? _this5.saveRef : undefined,
                record: record,
                name: fieldName,
                onKeyDown: _this5.handleEditorKeyDown,
                onEnterDown: _this5.handleEditorKeyEnterDown,
                onClick: _this5.handleEditorClick,
                tabIndex: -1,
                showHelp: ShowHelp.none,
                showValidation: ShowValidation.tooltip,
                labelLayout: LabelLayout.none,
                // 目前测试inline时候需要放开限制
                _inTable: !inlineEdit,
                preventRenderer: true
              });

              ref = false;
              var label = field.get('label', record);
              var key = "".concat(record.index, "-multi-").concat(fieldName);
              multiLineFields.push( /*#__PURE__*/React.createElement(Row, {
                key: key,
                className: "".concat(prefixCls, "-multi")
              }, label && /*#__PURE__*/React.createElement(Col, {
                span: 8,
                className: "".concat(prefixCls, "-multi-label")
              }, label), /*#__PURE__*/React.createElement(Col, {
                span: label ? 16 : 24,
                className: "".concat(prefixCls, "-multi-value")
              }, /*#__PURE__*/cloneElement(editor, newEditorProps))));
            }
          });

          if (multiLineFields.length) {
            return /*#__PURE__*/React.createElement("div", null, multiLineFields);
          }
        }
      }
    }
  }, {
    key: "renderEditor",
    value: function renderEditor() {
      var column = this.props.column;
      var name = column.name;

      if (name) {
        var _this$context3 = this.context,
            dataSet = _this$context3.dataSet,
            pristine = _this$context3.pristine,
            inlineEdit = _this$context3.inlineEdit,
            _this$context3$tableS = _this$context3.tableStore,
            currentEditRecord = _this$context3$tableS.currentEditRecord,
            currentEditorName = _this$context3$tableS.currentEditorName,
            getColumnTagRenderer = _this$context3$tableS.getColumnTagRenderer,
            rowHeight = _this$context3.rowHeight;
        var record = currentEditRecord || dataSet.current;
        var field = dataSet.getField(name); // 多行编辑拦截返回渲染器

        if (!pristine && field && field.get('multiLine', record)) {
          return this.renderMultiLineEditor();
        }

        var cellEditor = getEditorByColumnAndRecord(column, record);

        if (!pristine && /*#__PURE__*/isValidElement(cellEditor) && !isInCellEditor(cellEditor)) {
          this.editorProps = cellEditor.props;
          var height = this.height;

          var _this$editorProps = this.editorProps,
              _this$editorProps$sty = _this$editorProps.style,
              style = _this$editorProps$sty === void 0 ? {} : _this$editorProps$sty,
              editorTagRenderer = _this$editorProps.tagRenderer,
              otherProps = _objectWithoutProperties(_this$editorProps, _excluded2);

          var tagRenderer = editorTagRenderer || getColumnTagRenderer(column);

          if (height !== undefined) {
            style.height = pxToRem(height, true);
          }

          var newEditorProps = _objectSpread(_objectSpread({}, otherProps), {}, {
            style: style,
            ref: this.saveRef,
            record: record,
            name: name,
            tagRenderer: tagRenderer,
            onKeyDown: this.handleEditorKeyDown,
            onEnterDown: isTextArea(cellEditor) ? undefined : this.handleEditorKeyEnterDown,
            onBlur: this.handleEditorBlur,
            tabIndex: currentEditorName ? 0 : -1,
            showHelp: ShowHelp.none,
            showValidation: ShowValidation.tooltip,
            labelLayout: LabelLayout.none,
            // 目前测试inline时候需要放开限制
            _inTable: !inlineEdit,
            preventRenderer: true
          });

          if (isTextArea(cellEditor)) {
            var resize = newEditorProps.resize || cellEditor.props.resize || ResizeType.vertical;
            newEditorProps.resize = resize;

            if (resize !== ResizeType.none) {
              newEditorProps.onResize = this.handleEditorResize;

              if (rowHeight === 'auto') {
                newEditorProps.autoSize = true;
              }
            }
          }

          return /*#__PURE__*/cloneElement(cellEditor, newEditorProps);
        }
      }

      this.cellNode = undefined;
    }
  }, {
    key: "render",
    value: function render() {
      var _this6 = this;

      if (this.rendered) {
        var editor = this.renderEditor();

        if (editor) {
          var lock = this.props.column.lock;
          var prefixCls = this.context.prefixCls;
          var props = {
            className: classNames("".concat(prefixCls, "-editor"), _defineProperty({}, "".concat(prefixCls, "-editor-lock"), isStickySupport() && lock))
          };
          return /*#__PURE__*/React.createElement("div", _extends({}, props, {
            ref: this.saveWrap
          }), editor);
        }

        var tableStore = this.context.tableStore;

        if (!tableStore.inlineEdit) {
          runInAction(function () {
            _this6.rendered = false;
          });
        }
      }

      return null;
    }
  }], [{
    key: "contextType",
    get: function get() {
      return TableContext;
    }
  }]);

  return TableEditor;
}(Component);

TableEditor.displayName = 'TableEditor';

__decorate([observable], TableEditor.prototype, "height", void 0);

__decorate([observable], TableEditor.prototype, "rendered", void 0);

__decorate([autobind], TableEditor.prototype, "handleWindowResize", null);

__decorate([autobind], TableEditor.prototype, "handleWindowClick", null);

__decorate([autobind], TableEditor.prototype, "saveRef", null);

__decorate([autobind], TableEditor.prototype, "saveWrap", null);

__decorate([autobind], TableEditor.prototype, "handleEditorKeyEnterDown", null);

__decorate([autobind], TableEditor.prototype, "handleKeyDownCTRLD", null);

__decorate([autobind], TableEditor.prototype, "handleKeyDownCTRLS", null);

__decorate([autobind], TableEditor.prototype, "handleEditorKeyDown", null);

__decorate([autobind], TableEditor.prototype, "handleEditorBlur", null);

__decorate([autobind], TableEditor.prototype, "handleEditorClick", null);

__decorate([autobind], TableEditor.prototype, "handleEditorResize", null);

__decorate([action], TableEditor.prototype, "alignEditor", null);

__decorate([autobind], TableEditor.prototype, "hideEditor", null);

TableEditor = __decorate([observer], TableEditor);
export default TableEditor;
//# sourceMappingURL=TableEditor.js.map
