import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
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";
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && _getIteratorMethod(r) || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { var _context2; if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = _sliceInstanceProperty(_context2 = {}.toString.call(r)).call(_context2, 8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import SpanManager from '../base/helpers/SpanManager';
import { internals } from '../internals';
import collectNodes from './collectNodes';
import getTreeDepth from './getTreeDepth';
import isLeafNode from './isLeafNode';
function safeGetSpanRect(column, record, rowIndex, colIndex) {
  var colSpan = 1;
  var rowSpan = 1;
  if (column.getSpanRect) {
    var value = internals.safeGetValue(column, record, rowIndex);
    var spanRect = column.getSpanRect(value, record, rowIndex);
    colSpan = spanRect == null ? 1 : spanRect.right - colIndex;
    rowSpan = spanRect == null ? 1 : spanRect.bottom - rowIndex;
  } else {
    var cellProps = internals.safeGetCellProps(column, record, rowIndex);
    if (cellProps.colSpan != null) {
      colSpan = cellProps.colSpan;
    }
    if (cellProps.rowSpan != null) {
      rowSpan = cellProps.rowSpan;
    }
  }
  // 注意这里没有考虑「rowSpan/colSpan 不能过大，避免 rowSpan/colSpan 影响因虚拟滚动而未渲染的单元格」
  return {
    top: rowIndex,
    bottom: rowIndex + rowSpan,
    left: colIndex,
    right: colIndex + colSpan
  };
}
function move(_ref, dx, dy) {
  var c = _ref.c,
    r = _ref.r;
  return {
    c: c + dx,
    r: r + dy
  };
}
function sanitizeCellDatum(value) {
  if (value === Infinity || value === -Infinity || typeof value === 'number' && isNaN(value)) {
    return null;
  } else {
    return value;
  }
}
/** 根据 BaseTable 的 dataSource 和 column，将表格数据导出为 Excel 文件 */
export default function exportTableAsExcel(xlsxPackage, dataSource, columns, filename) {
  var sheet = xlsxPackage.utils.aoa_to_sheet([]);
  var topHeaderHeight = getTreeDepth(columns) + 1;
  var origin = {
    c: 0,
    r: 0
  };
  addTopHeaders(origin);
  addDataPart(move(origin, 0, topHeaderHeight));
  xlsxPackage.writeFile({
    SheetNames: ['Sheet1'],
    Sheets: {
      Sheet1: sheet
    }
  }, filename);
  function addTopHeaders(origin) {
    dfs(columns, 0, 0);
    function dfs(cols, startDx, startDy) {
      var _a;
      var start = move(origin, startDx, startDy);
      var offsetX = 0;
      var _iterator = _createForOfIteratorHelper(cols),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var col = _step.value;
          if ((_a = col.features) === null || _a === void 0 ? void 0 : _a.noExport) {
            continue;
          }
          var current = move(start, offsetX, 0);
          addOne(col.name, current);
          if (isLeafNode(col)) {
            offsetX += 1;
            mergeCells(current, 1, topHeaderHeight - startDy);
          } else {
            var childrenWidth = dfs(col.children, startDx + offsetX, startDy + 1);
            mergeCells(current, childrenWidth, 1);
            offsetX += childrenWidth;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
      return offsetX;
    }
  }
  function addDataPart(origin) {
    var _context;
    var leafColumns = _filterInstanceProperty(_context = collectNodes(columns, 'leaf-only')).call(_context, function (col) {
      var _a;
      return !((_a = col.features) === null || _a === void 0 ? void 0 : _a.noExport);
    });
    var spanManager = new SpanManager();
    var dataPart = _mapInstanceProperty(dataSource).call(dataSource, function (record, rowIndex) {
      spanManager.stripUpwards(rowIndex);
      return _mapInstanceProperty(leafColumns).call(leafColumns, function (col, colIndex) {
        if (spanManager.testSkip(rowIndex, colIndex)) {
          return null;
        }
        var spanRect = safeGetSpanRect(col, record, rowIndex, colIndex);
        var rowSpan = spanRect.bottom - spanRect.top;
        var colSpan = spanRect.right - spanRect.left;
        if (rowSpan > 1 || colSpan > 1) {
          spanManager.add(spanRect.top, spanRect.left, colSpan, rowSpan);
          mergeCells(move(origin, spanRect.left, spanRect.top), colSpan, rowSpan);
        }
        return sanitizeCellDatum(internals.safeGetValue(col, record, rowIndex));
      });
    });
    add(dataPart, origin);
  }
  function add(data, origin) {
    xlsxPackage.utils.sheet_add_aoa(sheet, data, {
      origin: origin
    });
  }
  function addOne(datum, origin) {
    xlsxPackage.utils.sheet_add_aoa(sheet, [[datum]], {
      origin: origin
    });
  }
  function mergeCells(addr, width, height) {
    if (width === 1 && height === 1) {
      return;
    }
    if (sheet['!merges'] == null) {
      sheet['!merges'] = [];
    }
    sheet['!merges'].push({
      s: addr,
      e: move(addr, width - 1, height - 1)
    });
  }
}