"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.removeTable = exports.removeRow = exports.removeColumn = exports.insertTableElement = exports.insertRow = exports.insertColumn = exports.changeColumnAlign = void 0;
var _slate = require("slate");
var _constants = require("../../constants");
var _helper = require("./helper");
var _model = require("./model");
var _core = require("../../core");
var _constant = require("./constant");
var _elementTypes = require("../../constants/element-types");
/**
 * @param {Object} editor
 * @param {INSERT_POSITION.AFTER | INSERT_POSITION.BEFORE} insertPosition by default is INSERT_POSITION.AFTER
 */
const insertRow = function (editor) {
  let position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.INSERT_POSITION.AFTER;
  const {
    tableEntry: [, tablePath],
    rowEntry: [rowNode],
    rowIndex
  } = (0, _helper.getTableFocusingInfos)(editor);
  const getInsertPath = rowIndex => {
    const handlePosition = {
      [_constants.INSERT_POSITION.BEFORE]: rowIndex => tablePath.concat(rowIndex),
      [_constants.INSERT_POSITION.AFTER]: rowIndex => tablePath.concat(rowIndex + 1)
    };
    return handlePosition[position](rowIndex);
  };
  const insertPath = getInsertPath(rowIndex);
  const insertRowChildren = rowNode.children.map(_ref => {
    let {
      align
    } = _ref;
    return (0, _model.generateTableCell)({
      align
    });
  });
  const insertRow = (0, _model.generateTableRow)({
    childrenOrText: insertRowChildren
  });
  _slate.Transforms.insertNodes(editor, insertRow, {
    at: insertPath
  });
};
exports.insertRow = insertRow;
const removeRow = editor => {
  const isSelectMultipleTable = (0, _helper.isSelectingMultipleTables)(editor);
  if (isSelectMultipleTable) return;
  const selectInfo = (0, _helper.getSelectGrid)(editor);
  const [tableEntry] = (0, _helper.getTableEntry)(editor);
  if (!tableEntry) return;
  if (selectInfo) {
    const {
      startRowIndex,
      endRowIndex
    } = selectInfo;
    const [table, tablePath] = tableEntry;
    const tableRowCount = table.children.length;

    // Remove all rows
    if (startRowIndex === 0 && endRowIndex === tableRowCount - 1) return removeTable(editor);
    for (let index = endRowIndex; index >= startRowIndex; index--) {
      const rowPath = tablePath.concat(index);
      _slate.Transforms.removeNodes(editor, {
        at: rowPath
      });
    }
    const focusPoint = _slate.Editor.start(editor, tableEntry[1].concat(startRowIndex - 1 < 0 ? 0 : startRowIndex - 1));
    (0, _core.focusEditor)(editor, focusPoint);
    return;
  }
  const {
    tableEntry: [tableNode, tablePath],
    rowEntry: [, rowPath],
    rowIndex
  } = (0, _helper.getTableFocusingInfos)(editor);
  let focusPoint = null;
  const tableHeight = tableNode.children.length;
  // If table has one more row, remove row, else remove table
  if (tableHeight > 1) {
    // If removing row is the last row, focus on the previous row
    const isRemovingLastRow = rowIndex === tableHeight - 1;
    focusPoint = isRemovingLastRow ? _slate.Editor.start(editor, tablePath.concat(rowIndex - 1)) : _slate.Editor.start(editor, rowPath);
    _slate.Transforms.removeNodes(editor, {
      at: rowPath
    });
    (0, _core.focusEditor)(editor, focusPoint);
  } else {
    return removeTable(editor);
  }
};
exports.removeRow = removeRow;
const removeTable = editor => {
  const [tableNodeEntry] = (0, _helper.getTableEntry)(editor);
  if (!tableNodeEntry) return;
  const [table, tablePath] = tableNodeEntry;
  const isLast = (0, _core.isLastNode)(editor, table);
  if (isLast) {
    const paragraph = (0, _core.generateDefaultParagraph)();
    _slate.Transforms.removeNodes(editor, {
      at: tablePath
    });
    _slate.Transforms.insertNodes(editor, paragraph, {
      at: tablePath
    });
    const focusPoint = _slate.Editor.start(editor, tablePath);
    (0, _core.focusEditor)(editor, focusPoint);
    return;
  }
  const focusPoint = _slate.Editor.start(editor, tablePath[1]);
  _slate.Transforms.removeNodes(editor, {
    at: tablePath
  });
  (0, _core.focusEditor)(editor, focusPoint);
};

/**
 * @param {Object} editor
 * @param {INSERT_POSITION.AFTER | INSERT_POSITION.BEFORE} insertPosition by default is INSERT_POSITION.AFTER
 */
exports.removeTable = removeTable;
const insertColumn = function (editor) {
  let insertPosition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.INSERT_POSITION.AFTER;
  const {
    tableEntry: [tableNode, tablePath],
    rowIndex,
    columnIndex
  } = (0, _helper.getTableFocusingInfos)(editor);
  const getInsertPath = (rowIndex, columnIndex) => {
    const newCellPath = {
      [_constants.INSERT_POSITION.BEFORE]: (rowIndex, columnIndex) => tablePath.concat(rowIndex, columnIndex),
      [_constants.INSERT_POSITION.AFTER]: (rowIndex, columnIndex) => tablePath.concat(rowIndex, columnIndex + 1)
    };
    return newCellPath[insertPosition](rowIndex, columnIndex);
  };
  tableNode.children.forEach((row, rowIndex) => {
    const insertPath = getInsertPath(rowIndex, columnIndex);
    const newCell = (0, _model.generateTableCell)(rowIndex, columnIndex);
    _slate.Transforms.insertNodes(editor, newCell, {
      at: insertPath
    });
  });
  const align = [...tableNode.align];
  const insertAlgin = insertPosition === _constants.INSERT_POSITION.BEFORE ? columnIndex : columnIndex + 1;
  align.splice(insertAlgin, 0, _constants.TEXT_ALIGN.LEFT);
  _slate.Transforms.setNodes(editor, {
    align
  }, {
    at: tablePath
  });
  const focusPoint = _slate.Editor.start(editor, getInsertPath(rowIndex, columnIndex));
  (0, _core.focusEditor)(editor, focusPoint);
};
exports.insertColumn = insertColumn;
const removeColumn = editor => {
  const isSelectMultipleTable = (0, _helper.isSelectingMultipleTables)(editor);
  if (isSelectMultipleTable) return;
  const selectInfos = (0, _helper.getSelectGrid)(editor);
  const [tableEntry] = (0, _helper.getTableEntry)(editor);
  if (!tableEntry) return;
  if (selectInfos) {
    const {
      startColIndex,
      endColIndex
    } = selectInfos;
    const [table, tablePath] = tableEntry;
    const tableRowCount = table.children.length;
    const tableColumnCount = table.children[0].children.length;

    // Remove all columns
    if (startColIndex === 0 && endColIndex === tableColumnCount - 1) return removeTable(editor);
    for (let rowIndex = 0; rowIndex < tableRowCount; rowIndex++) {
      for (let colIndex = endColIndex; colIndex >= startColIndex; colIndex--) {
        const cellPath = tablePath.concat(rowIndex, colIndex);
        _slate.Transforms.removeNodes(editor, {
          at: cellPath
        });
      }
    }
    const focusPoint = _slate.Editor.start(editor, tablePath.concat(0, startColIndex - 1 < 0 ? 0 : startColIndex - 1));
    (0, _core.focusEditor)(editor, focusPoint);
    return;
  }
  const {
    tableEntry: [tableNode, tablePath],
    rowEntry: [rowNode, rowPath],
    columnIndex
  } = (0, _helper.getTableFocusingInfos)(editor);
  const tableWidth = rowNode.children.length;
  let focusPoint = null;

  // If table has one more column, remove column, else remove table
  if (tableWidth > 1) {
    // If removing column is the last column, focus on the previous column
    const isRemovingLastColumn = columnIndex === tableWidth - 1;
    tableNode.children.forEach((row, rowIndex) => {
      const removePath = tablePath.concat(rowIndex, columnIndex);
      _slate.Transforms.removeNodes(editor, {
        at: removePath
      });
    });

    // Update columns
    const align = [...tableNode.align];
    align.splice(columnIndex, 1);
    _slate.Transforms.setNodes(editor, {
      align
    }, {
      at: tablePath
    });
    focusPoint = isRemovingLastColumn ? _slate.Editor.start(editor, rowPath.concat(columnIndex - 1)) : _slate.Editor.start(editor, rowPath.concat(columnIndex));
    (0, _core.focusEditor)(editor, focusPoint);
  } else {
    removeTable(editor);
  }
};

/**
 * @param {Object} editor
 * @param {keyof TEXT_ALIGN} align Text align
 */
exports.removeColumn = removeColumn;
const changeColumnAlign = (editor, alignType) => {
  const {
    tableEntry: [table, tablePath],
    columnIndex
  } = (0, _helper.getTableFocusingInfos)(editor);
  const selectGrid = (0, _helper.getSelectGrid)(editor);
  const align = [...table.align];

  // If select a range in table
  if (selectGrid) {
    const {
      startColIndex,
      endColIndex
    } = selectGrid;
    for (let columnIndex = startColIndex; columnIndex <= endColIndex; columnIndex++) {
      align.splice(columnIndex, columnIndex, alignType);
    }
  } else {
    // If select a cell in table
    align.splice(columnIndex, columnIndex, alignType);
  }
  _slate.Transforms.setNodes(editor, {
    align
  }, {
    at: tablePath
  });
};
exports.changeColumnAlign = changeColumnAlign;
const insertTableElement = function (editor, type) {
  let position = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _constant.TABLE_ELEMENT_POSITION.AFTER;
  let count = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
  const [tableEntry] = (0, _helper.getTableEntry)(editor);
  if (!tableEntry) return;
  let selectedInfo = (0, _helper.getSelectGrid)(editor);
  if (!selectedInfo) {
    const tableCellEntry = (0, _core.getSelectedNodeEntryByType)(editor, _elementTypes.TABLE_CELL);
    const cellPath = tableCellEntry[1];
    const rowPath = cellPath.slice(0, cellPath.length - 1);
    selectedInfo = {
      endRowIndex: rowPath.pop(),
      endColIndex: cellPath.pop()
    };
  }
  const [tableNode, tablePath] = tableEntry;
  const tableRows = tableNode.children;
  const tableRowsLength = tableRows.length;
  const tableColumnLength = tableRows[0].children.length;
  const {
    endRowIndex,
    endColIndex
  } = selectedInfo;
  if (type === _constant.TABLE_ELEMENT.ROW) {
    if (tableRowsLength >= _constant.TABLE_MAX_ROWS) return;
    const targetPath = position === _constant.TABLE_ELEMENT_POSITION.AFTER ? [...tablePath, endRowIndex + 1] : [...tablePath, endRowIndex];
    const validCount = Math.min(_constant.TABLE_MAX_ROWS - tableRowsLength, count);
    for (let i = 0; i < validCount; i++) {
      const row = (0, _model.generateTableRow)({
        columnNum: tableColumnLength
      });
      _slate.Transforms.insertNodes(editor, row, {
        at: targetPath
      });
    }
    setTimeout(() => {
      const oldRowIndex = position === _constant.TABLE_ELEMENT_POSITION.AFTER ? endRowIndex : endRowIndex + validCount;
      const focusPath = [...tablePath, oldRowIndex, endColIndex];
      (0, _core.focusEditor)(editor, focusPath);
      _slate.Transforms.collapse(editor, {
        edge: 'end'
      });
    });
    return;
  }
  if (type === _constant.TABLE_ELEMENT.COLUMN) {
    if (tableColumnLength >= _constant.TABLE_MAX_COLUMNS) return;
    const newCellIndex = position === _constant.TABLE_ELEMENT_POSITION.AFTER ? endColIndex + 1 : endColIndex;
    const validCount = Math.min(_constant.TABLE_MAX_COLUMNS - tableColumnLength, count);
    for (let j = 0; j < validCount; j++) {
      for (let i = 0; i < tableRowsLength; i++) {
        const newCellPath = [...tablePath, i, newCellIndex];
        const newCell = (0, _model.generateTableCell)();
        _slate.Transforms.insertNodes(editor, newCell, {
          at: newCellPath
        });
      }
    }
    setTimeout(() => {
      const oldCellIndex = position === _constant.TABLE_ELEMENT_POSITION.AFTER ? endColIndex : endColIndex + validCount;
      const focusPath = [...tablePath, endRowIndex, oldCellIndex, 0];
      (0, _core.focusEditor)(editor, focusPath);
      _slate.Transforms.collapse(editor, {
        edge: 'end'
      });
    });
    return;
  }
};
exports.insertTableElement = insertTableElement;