import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import { Component, Children } from 'react';
import classNames from 'classnames';
import './sortable.less';
var Sortable = /*#__PURE__*/function (_Component) {
  function Sortable() {
    var _this;
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    _this = _Component.call.apply(_Component, [this].concat(args)) || this;
    _this.shell = void 0;
    _this.items = void 0;
    _this.willDetach = void 0;
    return _this;
  }
  _inheritsLoose(Sortable, _Component);
  var _proto = Sortable.prototype;
  _proto.componentDidMount = function componentDidMount() {
    var _this2 = this;
    var box = this.shell;
    var isDragEnd = false;

    /**
     * target node to be dragged
     */
    var source;

    /**
     * node to be placed
     */
    var ref;

    /**
     * next sibling of the source node
     */
    var origRef;

    /**
     * accurately locate the node from event
     */
    var locate = function locate(e) {
      var y = e.clientY;
      if (e.view !== window && e.view.frameElement) {
        y += e.view.frameElement.getBoundingClientRect().top;
      }
      var node = box.firstElementChild;
      while (node) {
        if (node !== source && node.dataset.id) {
          var rect = node.getBoundingClientRect();
          if (rect.height <= 0) continue;
          if (y < rect.top + rect.height / 2) {
            break;
          }
        }
        node = node.nextElementSibling;
      }
      return node;
    };

    /**
     * find the source node
     */
    var getSource = function getSource(e) {
      var target = e.target;
      if (!target || !box.contains(target) || target === box) {
        return null;
      }
      var node = box.firstElementChild;
      while (node) {
        if (node.contains(target)) {
          return node;
        }
        node = node.nextElementSibling;
      }
      return null;
    };
    var sort = function sort(beforeId) {
      if (!source) return;
      var sourceId = source.dataset.id;
      var items = _this2.items;
      var origIndex = items.findIndex(function (id) {
        return id == sourceId;
      });
      var newIndex = beforeId ? items.findIndex(function (id) {
        return id == beforeId;
      }) : items.length;
      if (origIndex < 0 || newIndex < 0) return;
      if (_this2.props.onSort) {
        if (newIndex > origIndex) {
          newIndex -= 1;
        }
        if (origIndex === newIndex) return;
        var item = items.splice(origIndex, 1);
        items.splice(newIndex, 0, item[0]);
        _this2.props.onSort(items);
      }
    };
    var dragstart = function dragstart(e) {
      isDragEnd = false;
      source = getSource(e);
      if (!source) {
        return false;
      }
      origRef = source.nextElementSibling;
      var rect = source.getBoundingClientRect();
      var dragSource = source;
      if (_this2.props.dragImageSourceHandler) {
        dragSource = _this2.props.dragImageSourceHandler(source);
      }
      if (e.dataTransfer) {
        e.dataTransfer.setDragImage(dragSource, e.clientX - rect.left, e.clientY - rect.top);
        e.dataTransfer.effectAllowed = 'move';
        e.dataTransfer.dropEffect = 'move';
        try {
          e.dataTransfer.setData('application/json', {});
        } catch (ex) {
          // eslint-disable-line
        }
      }
      setTimeout(function () {
        source.classList.add('lc-dragging');
      }, 0);
      return true;
    };
    var placeAt = function placeAt(beforeRef) {
      if (beforeRef) {
        if (beforeRef !== source) {
          box.insertBefore(source, beforeRef);
        }
      } else {
        box.appendChild(source);
      }
    };
    var adjust = function adjust(e) {
      if (isDragEnd) return;
      ref = locate(e);
      placeAt(ref);
    };
    var lastDragEvent;
    var drag = function drag(e) {
      if (!source) return;
      e.preventDefault();
      if (lastDragEvent) {
        if (lastDragEvent.clientX === e.clientX && lastDragEvent.clientY === e.clientY) {
          return;
        }
      }
      lastDragEvent = e;
      if (e.dataTransfer) {
        e.dataTransfer.effectAllowed = 'move';
      }
      adjust(e);
    };
    var dragend = function dragend(e) {
      isDragEnd = true;
      if (!source) return;
      e.preventDefault();
      source.classList.remove('lc-dragging');
      placeAt(origRef);
      sort(ref ? ref.dataset.id : null);
      source = null;
      ref = null;
      origRef = null;
      lastDragEvent = null;
    };
    box.addEventListener('dragstart', dragstart);
    document.addEventListener('dragover', drag);
    document.addEventListener('drag', drag);
    document.addEventListener('dragend', dragend);
    this.willDetach = function () {
      box.removeEventListener('dragstart', dragstart);
      document.removeEventListener('dragover', drag);
      document.removeEventListener('drag', drag);
      document.removeEventListener('dragend', dragend);
    };
  };
  _proto.componentWillUnmount = function componentWillUnmount() {
    if (this.willDetach) {
      this.willDetach();
    }
  };
  _proto.render = function render() {
    var _this3 = this;
    var _this$props = this.props,
      className = _this$props.className,
      itemClassName = _this$props.itemClassName,
      children = _this$props.children;
    var items = [];
    var cards = Children.map(children, function (child) {
      var id = child.key;
      items.push(id);
      return /*#__PURE__*/React.createElement("div", {
        key: id,
        "data-id": id,
        className: classNames('lc-sortable-card', itemClassName)
      }, child);
    });
    this.items = items;
    return /*#__PURE__*/React.createElement("div", {
      className: classNames('lc-sortable', className),
      ref: function ref(_ref) {
        _this3.shell = _ref;
      }
    }, cards);
  };
  return Sortable;
}(Component);
export default Sortable;