import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _extends from "@babel/runtime-corejs3/helpers/extends";
import _toConsumableArray from "@babel/runtime-corejs3/helpers/toConsumableArray";

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { var _context4; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context4 = Object.prototype.toString.call(o)).call(_context4, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols";
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol";
import _getIteratorMethod from "@babel/runtime-corejs3/core-js/get-iterator-method";

var __rest = this && this.__rest || function (s, e) {
  var t = {};

  for (var p in s) {
    if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  }

  if (s != null && typeof _Object$getOwnPropertySymbols === "function") for (var i = 0, p = _Object$getOwnPropertySymbols(s); i < p.length; i++) {
    if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  }
  return t;
};

import { getTreeDepth, isLeafNode } from '../../utils';
import { ROW_KEY } from './constants';
export default function buildCrossTable(options) {
  var _a, _b, _c;

  var leftTotalNode = options.leftTotalNode,
      topTotalNode = options.topTotalNode; // 有的时候 leftTree/topTree 是通过 node.children 传入的
  // 此时 leftTree/topTree 等于 null 和等于空数组是等价的
  // 故在这里兼容 leftTree/topTree 为空的情况

  var leftTree = (_a = options.leftTree) !== null && _a !== void 0 ? _a : [];
  var topTree = (_b = options.topTree) !== null && _b !== void 0 ? _b : [];
  var leftMetaColumns = (_c = options.leftMetaColumns) !== null && _c !== void 0 ? _c : [];
  var leftHeaderWidth = Math.max(leftMetaColumns.length, getTreeDepth(leftTree) + 1);
  return {
    columns: getColumns(),
    dataSource: getDataSource()
  };
  /** 获取表格的列配置 */

  function getColumns() {
    var _context;

    return _concatInstanceProperty(_context = []).call(_context, _toConsumableArray(getLeftPartColumns()), _toConsumableArray(getDataPartColumns()));

    function getLeftPartColumns() {
      var _a;

      var leftPartColumns = [];

      for (var index = 0; index < leftHeaderWidth; index++) {
        var metaCol = (_a = leftMetaColumns[index]) !== null && _a !== void 0 ? _a : {};

        var getCellProps = metaCol.getCellProps,
            render = metaCol.render,
            staticMetaColConfig = __rest(metaCol, ["getCellProps", "render"]);

        leftPartColumns.push(_extends(_extends({
          columnType: 'left',
          lock: true
        }, staticMetaColConfig), {
          getCellProps: leftHeaderGetCellPropsFactory(metaCol, index),
          getSpanRect: leftHeaderGetSpanRectFactory(metaCol, index),
          getValue: leftHeaderGetValueFactory(metaCol, index),
          render: leftHeaderRenderFactory(metaCol, index)
        }));
      }

      return leftPartColumns;

      function leftHeaderGetCellPropsFactory(metaCol, colIndex) {
        return function (_value, row, rowIndex) {
          var _a;

          var node = row.nodes[colIndex];
          return (_a = metaCol.getCellProps) === null || _a === void 0 ? void 0 : _a.call(metaCol, node, colIndex);
        };
      }

      function leftHeaderGetSpanRectFactory(metaCol, colIndex) {
        return function (_value, row) {
          return row.rects[colIndex];
        };
      }

      function leftHeaderGetValueFactory(metaCol, colIndex) {
        return function (row, rowIndex) {
          var node = row.nodes[colIndex];
          return node.value;
        };
      }

      function leftHeaderRenderFactory(metaCol, colIndex) {
        return function (v, row, rowIndex) {
          var _a;

          var node = row.nodes[colIndex];

          if (metaCol.render) {
            return metaCol.render(node, colIndex);
          }

          return (_a = node.title) !== null && _a !== void 0 ? _a : node.value;
        };
      }
    }
    /** 获取表格数据部分的列配置 */


    function getDataPartColumns() {
      if (topTree.length > 0) {
        return dfs(topTree, {
          valuePath: [],
          depth: 0
        });
      } else if (topTotalNode) {
        return dfs([topTotalNode], {
          valuePath: [],
          depth: 0
        });
      } else {
        return [];
      }

      function dfs(nodes, ctx) {
        var result = [];

        var _iterator = _createForOfIteratorHelper(nodes),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var node = _step.value;
            ctx.valuePath.push(node.value);

            if (isLeafNode(node)) {
              // 叶子节点
              result.push(getDataColumn(node, ctx.depth));
            } else {
              var key = node.key,
                  value = node.value,
                  children = node.children,
                  others = __rest(node // 强制展开的节点
              , ["key", "value", "children"]); // 强制展开的节点


              result.push(_extends(_extends({
                columnType: 'data-parent'
              }, others), {
                name: value,
                children: dfs(children, {
                  valuePath: ctx.valuePath,
                  depth: ctx.depth + 1
                })
              }));
            }

            ctx.valuePath.pop();
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }

        return result;
      }
    }

    function getDataColumn(topNode, topDepth) {
      var columnGetValue = function columnGetValue(row) {
        var leftDepth = row.nodes.length - 1;
        var leftNode = row.nodes[leftDepth];
        return options.getValue(leftNode, topNode, leftDepth, topDepth);
      };

      var key = topNode.key,
          value = topNode.value,
          children = topNode.children,
          others = __rest(topNode, ["key", "value", "children"]);

      return _extends(_extends({
        columnType: 'data'
      }, others), {
        getValue: columnGetValue,
        name: value,
        children: null,
        render: function render(value, row) {
          if (options.render) {
            var leftDepth = row.nodes.length - 1;
            var leftNode = row.nodes[leftDepth];
            return options.render(value, leftNode, topNode, leftDepth, topDepth);
          }

          return value;
        },
        getCellProps: function getCellProps(value, row) {
          if (options.getCellProps) {
            var leftDepth = row.nodes.length - 1;
            var leftNode = row.nodes[leftDepth];
            return options.getCellProps(value, leftNode, topNode, leftDepth, topDepth);
          }
        }
      });
    }
  }

  function getDataSource() {
    var flatRows = [];
    var ctx = {
      depth: 0,
      nodes: [],
      rects: [],
      rowIndex: 0
    };

    if (leftTree.length > 0) {
      dfs(leftTree, ctx);
    } else if (leftTotalNode) {
      dfs([leftTotalNode], ctx);
    } // else 表格没有行，展示空表格


    return flatRows;

    function dfs(nodes, ctx) {
      var count = 0;

      var _iterator2 = _createForOfIteratorHelper(nodes),
          _step2;

      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var _context2, _context3, _row;

          var node = _step2.value;

          if (node.hidden) {
            // 跳过被隐藏的节点
            continue;
          }

          var rect = {
            top: ctx.rowIndex + count,
            bottom: -1,
            left: ctx.depth,
            right: -1
          };
          var row = (_row = {}, _defineProperty(_row, ROW_KEY, node.key), _defineProperty(_row, "rects", _concatInstanceProperty(_context2 = []).call(_context2, _toConsumableArray(ctx.rects), [rect])), _defineProperty(_row, "nodes", _concatInstanceProperty(_context3 = []).call(_context3, _toConsumableArray(ctx.nodes), [node])), _row);

          if (isLeafNode(node)) {
            rect.right = leftHeaderWidth;
            rect.bottom = rect.top + 1;
            flatRows.push(row);
            count += 1;
          } else {
            ctx.rects.push(rect);
            ctx.nodes.push(node);
            var ret = dfs(node.children, {
              nodes: ctx.nodes,
              rects: ctx.rects,
              depth: ctx.depth + 1,
              rowIndex: ctx.rowIndex + count
            });
            ctx.rects.pop();
            ctx.nodes.pop();
            count += ret.count;
            rect.right = rect.left + 1;
            rect.bottom = rect.top + ret.count;
          }
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }

      return {
        count: count
      };
    }
  }
}