import _createClass from "@babel/runtime-corejs3/helpers/createClass";
import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck";
import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
import React, { useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
import cx from 'classnames';
import { ContextMenuStyleWrap } from '../../common-views';
import { copyDataToClipboard, executeOnTempElement, console, getEventPath, isElementInEventPath, getTargetEleInEventPath } from '../../utils';
import { findByTree } from '../../utils/others';
import { internals } from '../../internals';
import { MenuClasses } from '../../base/styles';
export function contextMenu() {
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  return function step(pipeline) {
    var popupParent = opts.popupParent || document.body;
    var menuClassName = opts.menuClassName;
    var menuHelper = new MenuHelper();

    var addPopup = function addPopup(menu) {
      var ePopupDiv = document.createElement('div');
      ePopupDiv.setAttribute('class', 'kd-table-popup');
      popupParent.appendChild(ePopupDiv);
      var popupHidden = false;
      var eventList = ['mousedown', 'contextmenu'];

      var hidePopup = function hidePopup(event) {
        if (isEventFromCurrentPopup(event, ePopupDiv) || popupHidden) {
          return;
        }

        popupHidden = true;
        popupParent.removeChild(ePopupDiv);
        eventList.forEach(function (eventType) {
          window.removeEventListener(eventType, hidePopup, true);
        });
      };

      ReactDOM.render(menu, ePopupDiv, function () {
        setTimeout(function () {
          eventList.forEach(function (eventType) {
            window.addEventListener(eventType, hidePopup, true);
          });
        }, 0);
      });
      return hidePopup;
    };

    var onContextMenu = function onContextMenu(e) {
      if (canShowContextMenu(e, pipeline)) {
        e.preventDefault();
        e.stopPropagation();
        showContextMenu(e);
      }
    };

    pipeline.addTableProps({
      onContextMenu: onContextMenu
    });

    var getContextMenuOptions = function getContextMenuOptions(record, column, value, event) {
      var defaultMenuOptions = [];

      if (column) {
        defaultMenuOptions.push(getCopyItem(value));
      }

      if (opts.getContextMenuItems) {
        var params = {
          record: record,
          column: column,
          value: value,
          event: event
        };
        return opts.getContextMenuItems(params);
      }

      return defaultMenuOptions;
    };

    var hideContextMenu = function hideContextMenu() {
      menuHelper.destroy();
    };

    var getPopupParent = function getPopupParent() {
      return popupParent;
    };

    var showContextMenu = function showContextMenu(e) {
      var path = getEventPath(e);
      var cellEle = getCellEleInEventPath(path);
      var code;
      var rowIndex;
      var isInFooter;

      if (cellEle) {
        code = cellEle.getAttribute('data-code');
        rowIndex = cellEle.getAttribute('data-rowindex');
        isInFooter = isElementInsideTheFooter(cellEle);
      } else {
        var rowEle = getRowEleInEventPath(path);
        rowIndex = rowEle === null || rowEle === void 0 ? void 0 : rowEle.getAttribute('data-rowindex');
        isInFooter = isElementInsideTheFooter(rowEle);
      }

      var dataSource = isInFooter ? pipeline.getFooterDataSource() || [] : pipeline.getDataSource();
      var record = dataSource[rowIndex];
      var column = code !== undefined && findByTree(pipeline.getColumns(), function (item) {
        return item.code === code;
      });
      var value = column && record && internals.safeGetValue(column, record, rowIndex);
      var options = getContextMenuOptions(record, column, value, e);

      if (options.length === 0) {
        console.warn('context menu options is empty');
        return;
      }

      var position = positionForMenu(e, popupParent);
      var menu = /*#__PURE__*/React.createElement(Menu, {
        options: options,
        hideContextMenu: hideContextMenu,
        position: position,
        getPopupParent: getPopupParent,
        className: menuClassName
      });

      var _hidePopup = addPopup(menu);

      menuHelper.init(_hidePopup);
    };

    return pipeline;
  };
}

function getMenuItemKey(_ref) {
  var name = _ref.name,
      index = _ref.index;

  if (name) {
    var _context;

    var _key = 0;
    name = name + '';

    for (var i = 0; i < name.length; i++) {
      _key += name.charCodeAt(name[i]);
    }

    return _concatInstanceProperty(_context = "".concat(_key, "_")).call(_context, index);
  }

  return index;
}

function Menu(props) {
  var className = props.className,
      _props$options = props.options,
      options = _props$options === void 0 ? [] : _props$options,
      hideContextMenu = props.hideContextMenu,
      position = props.position,
      getPopupParent = props.getPopupParent;
  var menuRef = useRef();
  useEffect(function () {
    if (menuRef.current) {
      var popupParent = getPopupParent();
      var x = position.x,
          y = position.y;

      var _keepWithinBounds = keepWithinBounds(popupParent, menuRef.current, x, y),
          _x = _keepWithinBounds.x,
          _y = _keepWithinBounds.y;

      menuRef.current.style.left = _x + 'px';
      menuRef.current.style.top = _y + 'px';
    }
  }, [position]);
  return /*#__PURE__*/React.createElement(ContextMenuStyleWrap, {
    className: cx(MenuClasses.menu, className),
    ref: menuRef,
    style: {
      left: position.x,
      top: position.y
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: MenuClasses.menuList
  }, _mapInstanceProperty(options).call(options, function (item, index) {
    return /*#__PURE__*/React.createElement(MenuItem, {
      key: item.key ? item.key : getMenuItemKey({
        name: item.name,
        index: index
      }),
      name: item.name,
      action: item.action,
      className: item.className,
      disabled: item.disabled,
      hideContextMenu: hideContextMenu
    });
  })));
}

function MenuItem(props) {
  var name = props.name,
      action = props.action,
      className = props.className,
      disabled = props.disabled,
      hideContextMenu = props.hideContextMenu;
  var itemRef = useRef();

  var handleClick = function handleClick() {
    if (disabled) {
      return;
    }

    hideContextMenu();
    typeof action === 'function' && action();
  };

  var handleMouseEnter = function handleMouseEnter(e) {
    if (disabled) {
      return;
    }

    var itemDom = itemRef.current;

    if (itemDom) {
      itemDom.classList.add(MenuClasses.menuOptionActive);
    }
  };

  var handleMouseLeave = function handleMouseLeave(e) {
    if (disabled) {
      return;
    }

    var itemDom = itemRef.current;

    if (itemDom) {
      setTimeout(function () {
        itemDom.classList.remove(MenuClasses.menuOptionActive);
      }, 10);
    }
  };

  return /*#__PURE__*/React.createElement("div", {
    className: cx(MenuClasses.menuOption, className, _defineProperty({}, MenuClasses.menuOptionDisable, disabled)),
    ref: itemRef,
    onClick: handleClick,
    onMouseEnter: handleMouseEnter,
    onMouseLeave: handleMouseLeave
  }, /*#__PURE__*/React.createElement("span", {
    className: MenuClasses.menuOptionText
  }, name));
}

var MenuHelper = /*#__PURE__*/_createClass(function MenuHelper() {
  var _this = this;

  _classCallCheck(this, MenuHelper);

  this.init = function (hidePopup) {
    _this.hidePopup = hidePopup;
  };

  this.destroy = function () {
    _this.hidePopup && _this.hidePopup();
    _this.hidePopup = null;
  };
});
/** 是否点击是外部 start */


function isEventFromCurrentPopup(event, ele) {
  if (!event || !ele) {
    return false;
  }

  if (isElementInEventPath(ele, event)) {
    return true;
  }

  return false;
}
/** 是否点击是外部 end */

/** 计算位置 start */


function calculatePointerRelative(event, popupParent) {
  var parentRect = popupParent.getBoundingClientRect();
  var documentRect = document.documentElement.getBoundingClientRect();
  return {
    x: event.clientX - (popupParent === document.body ? documentRect.left : parentRect.left),
    y: event.clientY - (popupParent === document.body ? documentRect.top : parentRect.top)
  };
}

function positionForMenu(event, popupParent, params) {
  var _calculatePointerRela = calculatePointerRelative(event, popupParent),
      x = _calculatePointerRela.x,
      y = _calculatePointerRela.y;

  if (params) {
    var offsetX = params.offsetX,
        offsetY = params.offsetY;

    if (offsetX) {
      x -= offsetX;
    }

    if (offsetY) {
      y -= offsetY;
    }
  }

  return {
    x: x,
    y: y
  };
}

function keepWithinBounds(popupParent, ePopup, x, y) {
  var parentRect = popupParent.getBoundingClientRect();
  var docElement = document.documentElement;
  var documentRect = docElement.getBoundingClientRect();
  var ePopupRect = ePopup.getBoundingClientRect();
  var parentWidth = parentRect.width;
  var parentHeight = parentRect.height;

  if (popupParent === document.body) {
    parentWidth = documentRect.width;
    parentWidth -= Math.abs(documentRect.left - parentRect.left);
    parentHeight = documentRect.height + docElement.scrollTop;
    parentHeight -= Math.abs(documentRect.top - parentRect.top);
  }

  if (x) {
    var minWidth = Math.min(ePopupRect.width, 120);
    ePopup.style.minWidth = minWidth + 'px';
    var maxX = parentWidth - minWidth;
    x = Math.min(Math.max(x, 0), Math.abs(maxX)); // 目前位置，最大支持的位置
  }

  if (y) {
    var minHeight = Math.min(ePopupRect.height, 180);
    var maxY = parentHeight - minHeight;
    y = Math.min(Math.max(y, 0), Math.abs(maxY)); // 目前位置，最大支持的位置
  }

  return {
    x: x,
    y: y
  };
}
/** 计算位置 end */

/** 获得点击的元素 start */


function getCellEleInEventPath(path) {
  return getTargetEleInEventPath(path, function (ele) {
    return ele && ele.getAttribute('data-role') === 'table-cell';
  });
}

function getRowEleInEventPath(path) {
  return getTargetEleInEventPath(path, function (ele) {
    return ele && ele.getAttribute('data-role') === 'table-row';
  });
}
/** 获得点击的元素 end */


function isElementInsideTheFooter(ele) {
  var pointer = ele;

  while (pointer) {
    if (pointer.tagName === 'TFOOT') {
      return true;
    }

    if (pointer.tagName === 'TABLE' || pointer.tagName === 'TBODY') {
      return false;
    }

    pointer = pointer.parentElement;
  }

  return false;
}

function canShowContextMenu(e, pipeline) {
  var _a, _b;

  return ((_a = pipeline.ref.current.domHelper) === null || _a === void 0 ? void 0 : _a.tableBody.contains(e.target)) || ((_b = pipeline.ref.current.domHelper) === null || _b === void 0 ? void 0 : _b.tableFooter.contains(e.target));
} // 默认选项


function getCopyItem(v) {
  return {
    name: '复制',
    action: function action() {
      executeOnTempElement(copyDataToClipboard(v));
    }
  };
}