import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
var _excluded = ["bordered", "children", "className", "processing", "comparableId", "selectable", "stickyFromLeft", "stickyFromRight", "onSelectionChange"];
import cx from 'classnames';
import omit from 'lodash.omit';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import ReactResizeDetector from 'react-resize-detector';
import Box from '../box';
import LoadingBar from '../loadingBar';
import isComponentOfType from '../utils/is-component-of-type';
import isReactElement from '../utils/is-react-element';
import { isElementOverflowingX } from '../utils/utils';
import BodyRow from './BodyRow';
import Cell from './Cell';
import FooterRow from './FooterRow';
import HeaderCell from './HeaderCell';
import HeaderRow from './HeaderRow';
import HeaderRowOverlay from './HeaderRowOverlay/HeaderRowOverlay';
import theme from './theme.css';
export var DataGrid = function DataGrid(_ref) {
  var _childrenArray$find, _cx, _cx2;

  var _ref$bordered = _ref.bordered,
      bordered = _ref$bordered === void 0 ? false : _ref$bordered,
      children = _ref.children,
      className = _ref.className,
      _ref$processing = _ref.processing,
      processing = _ref$processing === void 0 ? false : _ref$processing,
      comparableId = _ref.comparableId,
      selectable = _ref.selectable,
      _ref$stickyFromLeft = _ref.stickyFromLeft,
      stickyFromLeft = _ref$stickyFromLeft === void 0 ? 0 : _ref$stickyFromLeft,
      _ref$stickyFromRight = _ref.stickyFromRight,
      stickyFromRight = _ref$stickyFromRight === void 0 ? 0 : _ref$stickyFromRight,
      onSelectionChange = _ref.onSelectionChange,
      others = _objectWithoutProperties(_ref, _excluded);

  var _useState = useState(null),
      _useState2 = _slicedToArray(_useState, 2),
      hoveredRow = _useState2[0],
      setHoveredRow = _useState2[1];

  var _useState3 = useState(false),
      _useState4 = _slicedToArray(_useState3, 2),
      isOverflowing = _useState4[0],
      setOverflowing = _useState4[1];

  var _useState5 = useState([]),
      _useState6 = _slicedToArray(_useState5, 2),
      selectedRows = _useState6[0],
      setSelectedRows = _useState6[1];

  var scrollableNode = useRef(null);

  var _useState7 = useState(new Map()),
      _useState8 = _slicedToArray(_useState7, 2),
      rowNodes = _useState8[0],
      setRowNodes = _useState8[1];

  var totalRowChildrenWidth = useMemo(function () {
    return Array.from(rowNodes.values()).filter(function (rowDOMNode) {
      return rowDOMNode.children;
    }).map(function (rowDOMNode) {
      return Array.from(rowDOMNode.children).map(function (child) {
        return child.clientWidth;
      }).reduce(function (accumulatedChildWidth, currentChildWidth) {
        return accumulatedChildWidth + currentChildWidth;
      }, 0);
    }).reduce(function (maxRowWidth, currentRowWidth) {
      return currentRowWidth > maxRowWidth ? currentRowWidth : maxRowWidth;
    }, 0);
  }, [rowNodes, rowNodes.size]);
  var childrenArray = !Array.isArray(children) ? [children] : children;
  var bodyRowCount = (_childrenArray$find = childrenArray.find(function (child) {
    return Array.isArray(child);
  })) === null || _childrenArray$find === void 0 ? void 0 : _childrenArray$find.length;

  var handleSelectionChange = function handleSelectionChange(selection) {
    var event = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

    if (onSelectionChange) {
      onSelectionChange(selection, event);
    }
  };

  var handleHeaderRowSelectionChange = function handleHeaderRowSelectionChange(checked, event) {
    var allBodyRowIndexes = React.Children.map(children, function (child) {
      if (isReactElement(child) && isComponentOfType(BodyRow, child)) {
        return child.key;
      }
    });
    var selectedBodyRowIndexes = checked ? allBodyRowIndexes !== null && allBodyRowIndexes !== void 0 ? allBodyRowIndexes : [] : [];
    setSelectedRows(selectedBodyRowIndexes);
    handleSelectionChange(selectedBodyRowIndexes, event);
  };

  var handleBodyRowMouseEnter = function handleBodyRowMouseEnter(row, event) {
    var _row$props = row.props,
        onClick = _row$props.onClick,
        onMouseOver = _row$props.onMouseOver;
    onClick && setHoveredRow(row.key);
    onMouseOver && onMouseOver(event);
  };

  var handleBodyRowMouseLeave = function handleBodyRowMouseLeave(row, event) {
    var _row$props2 = row.props,
        onClick = _row$props2.onClick,
        onMouseOut = _row$props2.onMouseOut;
    onClick && setHoveredRow(null);
    onMouseOut && onMouseOut(event);
  };

  var handleBodyRowSelectionChange = function handleBodyRowSelectionChange(rowIndex, event) {
    if (rowIndex === null) {
      return;
    }

    var rows = selectedRows.includes(rowIndex) ? selectedRows.filter(function (row) {
      return row !== rowIndex;
    }) : [].concat(_toConsumableArray(selectedRows), [rowIndex]);
    setSelectedRows(rows);
    handleSelectionChange(rows, event);
  };

  var handleResize = function handleResize() {
    if (isElementOverflowingX(scrollableNode.current)) {
      setOverflowing(true);
    } else {
      setOverflowing(false);
    }
  };

  useEffect(function () {
    handleResize();
  });
  useEffect(function () {
    setSelectedRows([]);
    handleSelectionChange([]);
  }, [comparableId]);
  var classNames = cx(theme['data-grid'], (_cx = {}, _defineProperty(_cx, theme['is-bordered'], bordered), _defineProperty(_cx, theme['is-overflowing'], isOverflowing), _cx), className);
  var rest = omit(others, ['comparableId', 'onSelectionChange']);
  var sectionLeftClassNames = cx(theme['section'], theme['is-sticky-left'], (_cx2 = {}, _defineProperty(_cx2, theme['has-blend-right'], selectable || stickyFromLeft > 0), _defineProperty(_cx2, theme['has-border-right'], selectable || stickyFromLeft > 0), _cx2));
  return /*#__PURE__*/React.createElement(Box, _extends({
    "data-teamleader-ui": "data-grid",
    className: classNames
  }, rest), processing && /*#__PURE__*/React.createElement("div", {
    className: cx(theme['loading-bar'])
  }, /*#__PURE__*/React.createElement(LoadingBar, null)), selectedRows.length > 0 && React.Children.map(children, function (child) {
    if (isReactElement(child) && isComponentOfType(HeaderRowOverlay, child)) {
      return /*#__PURE__*/React.cloneElement(child, {
        numSelectedRows: selectedRows.length
      });
    }
  }), /*#__PURE__*/React.createElement(Box, {
    display: "flex",
    className: cx(theme['section-wrapper'])
  }, (selectable || stickyFromLeft > 0) && /*#__PURE__*/React.createElement("div", {
    className: sectionLeftClassNames
  }, React.Children.map(children, function (child) {
    if (isReactElement(child)) {
      if (isComponentOfType(HeaderRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          onSelectionChange: handleHeaderRowSelectionChange,
          selected: selectedRows.length === bodyRowCount,
          selectable: selectable,
          sliceTo: stickyFromLeft > 0 ? stickyFromLeft : 0
        });
      } else if (isComponentOfType(BodyRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          hovered: hoveredRow === child.key,
          onMouseEnter: function onMouseEnter(event) {
            return handleBodyRowMouseEnter(child, event);
          },
          onMouseLeave: function onMouseLeave(event) {
            return handleBodyRowMouseLeave(child, event);
          },
          onSelectionChange: function onSelectionChange(checked, event) {
            return handleBodyRowSelectionChange(child.key, event);
          },
          selected: child.key && selectedRows.indexOf(child.key) !== -1,
          selectable: selectable,
          sliceTo: stickyFromLeft > 0 ? stickyFromLeft : 0
        });
      } else if (isComponentOfType(FooterRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          preserveSelectableSpace: selectable,
          sliceTo: stickyFromLeft > 0 ? stickyFromLeft : 0
        });
      }
    }
  })), /*#__PURE__*/React.createElement("div", {
    className: cx(theme['section'], theme['is-scrollable']),
    ref: scrollableNode
  }, React.Children.map(children, function (child, key) {
    if (isReactElement(child)) {
      if (isComponentOfType(HeaderRow, child) || isComponentOfType(FooterRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          sliceFrom: stickyFromLeft > 0 ? stickyFromLeft : 0,
          sliceTo: stickyFromRight > 0 ? -stickyFromRight : undefined,
          ref: function ref(rowNode) {
            return setRowNodes(rowNodes.set(key, rowNode));
          },
          style: isOverflowing ? {
            minWidth: "".concat(totalRowChildrenWidth - 10, "px")
          } : undefined
        });
      } else if (isComponentOfType(BodyRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          hovered: hoveredRow === child.key,
          onMouseEnter: function onMouseEnter(event) {
            return handleBodyRowMouseEnter(child, event);
          },
          onMouseLeave: function onMouseLeave(event) {
            return handleBodyRowMouseLeave(child, event);
          },
          sliceFrom: stickyFromLeft > 0 ? stickyFromLeft : 0,
          sliceTo: stickyFromRight > 0 ? -stickyFromRight : undefined,
          ref: function ref(rowNode) {
            return setRowNodes(rowNodes.set(key, rowNode));
          },
          style: isOverflowing ? {
            minWidth: "".concat(totalRowChildrenWidth - 10, "px")
          } : undefined
        });
      }
    }
  })), stickyFromRight > 0 && /*#__PURE__*/React.createElement("div", {
    className: cx(theme['section'], theme['has-blend-left'])
  }, React.Children.map(children, function (child) {
    if (isReactElement(child)) {
      if (isComponentOfType(HeaderRow, child) || isComponentOfType(FooterRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          sliceFrom: -stickyFromRight
        });
      } else if (isComponentOfType(BodyRow, child)) {
        return /*#__PURE__*/React.cloneElement(child, {
          hovered: hoveredRow === child.key,
          onMouseEnter: function onMouseEnter(event) {
            return handleBodyRowMouseEnter(child, event);
          },
          onMouseLeave: function onMouseLeave(event) {
            return handleBodyRowMouseLeave(child, event);
          },
          sliceFrom: -stickyFromRight
        });
      }
    }
  }))), /*#__PURE__*/React.createElement(ReactResizeDetector, {
    handleWidth: true,
    onResize: handleResize,
    refreshMode: "throttle",
    refreshRate: 16
  }));
};
DataGrid.HeaderRow = HeaderRow;
DataGrid.HeaderRowOverlay = HeaderRowOverlay;
DataGrid.HeaderCell = HeaderCell;
DataGrid.BodyRow = BodyRow;
DataGrid.Cell = Cell;
DataGrid.FooterRow = FooterRow;
DataGrid.displayName = 'DataGrid';
export default DataGrid;