"use strict";

exports.__esModule = true;
exports.installFocusCatcher = installFocusCatcher;
var _shortcutContexts = require("../../shortcutContexts");
var _focusDetector = require("./focusDetector");
/**
 * Installs a focus catcher module. The module observes when the table is focused and depending on
 * from the which side it was focused on it selects a specified cell or releases the TAB navigation
 * to the browser.
 *
 * @param {Core} hot The Handsontable instance.
 */
function installFocusCatcher(hot) {
  let recentlyAddedFocusCoords;
  const {
    activate,
    deactivate
  } = (0, _focusDetector.installFocusDetector)(hot, {
    onFocusFromTop() {
      var _recentlyAddedFocusCo;
      const mostTopStartCoords = (_recentlyAddedFocusCo = recentlyAddedFocusCoords) !== null && _recentlyAddedFocusCo !== void 0 ? _recentlyAddedFocusCo : getMostTopStartPosition(hot);
      if (mostTopStartCoords) {
        hot.runHooks('modifyFocusOnTabNavigation', 'from_above', mostTopStartCoords);
        hot.selectCell(mostTopStartCoords.row, mostTopStartCoords.col);
      }
      hot.listen();
    },
    onFocusFromBottom() {
      var _recentlyAddedFocusCo2;
      const mostBottomEndCoords = (_recentlyAddedFocusCo2 = recentlyAddedFocusCoords) !== null && _recentlyAddedFocusCo2 !== void 0 ? _recentlyAddedFocusCo2 : getMostBottomEndPosition(hot);
      if (mostBottomEndCoords) {
        hot.runHooks('modifyFocusOnTabNavigation', 'from_below', mostBottomEndCoords);
        hot.selectCell(mostBottomEndCoords.row, mostBottomEndCoords.col);
      }
      hot.listen();
    }
  });
  hot.addHook('afterListen', () => deactivate());
  hot.addHook('afterUnlisten', () => activate());
  hot.addHook('afterSelection', () => {
    var _hot$getSelectedRange;
    recentlyAddedFocusCoords = (_hot$getSelectedRange = hot.getSelectedRangeLast()) === null || _hot$getSelectedRange === void 0 ? void 0 : _hot$getSelectedRange.highlight;
  });
  hot.getShortcutManager().getContext('grid').addShortcut({
    keys: [['Tab'], ['Shift', 'Tab']],
    callback: event => {
      var _hot$getSelectedRange2;
      const {
        disableTabNavigation,
        autoWrapRow
      } = hot.getSettings();
      if (disableTabNavigation) {
        hot.deselectCell();
        hot.unlisten();
        return false;
      }
      const isSelected = hot.selection.isSelected();
      const highlight = (_hot$getSelectedRange2 = hot.getSelectedRangeLast()) === null || _hot$getSelectedRange2 === void 0 ? void 0 : _hot$getSelectedRange2.highlight;
      const mostTopStartCoords = getMostTopStartPosition(hot);
      const mostBottomEndCoords = getMostBottomEndPosition(hot);

      // For disabled `autoWrapRow` option set the row to the same position as the currently selected row.
      if (!autoWrapRow) {
        mostTopStartCoords.row = highlight.row;
        mostBottomEndCoords.row = highlight.row;
      }
      if (event.shiftKey && (!isSelected || highlight.isEqual(mostTopStartCoords)) || !event.shiftKey && (!isSelected || highlight.isEqual(mostBottomEndCoords))) {
        hot.deselectCell();
        hot.unlisten();
        return false;
      }
      return true;
    },
    runOnlyIf: () => !hot.getSettings().minSpareCols,
    preventDefault: false,
    stopPropagation: false,
    position: 'before',
    relativeToGroup: _shortcutContexts.GRID_GROUP,
    group: 'focusCatcher'
  });
}

/**
 * Gets the coordinates of the most top-start cell or header (depends on the table settings and its size).
 *
 * @param {Core} hot The Handsontable instance.
 * @returns {CellCoords|null}
 */
function getMostTopStartPosition(hot) {
  const {
    rowIndexMapper,
    columnIndexMapper
  } = hot;
  const {
    navigableHeaders
  } = hot.getSettings();
  let topRow = navigableHeaders && hot.countColHeaders() > 0 ? -hot.countColHeaders() : 0;
  let startColumn = navigableHeaders && hot.countRowHeaders() > 0 ? -hot.countRowHeaders() : 0;
  if (topRow === 0) {
    topRow = rowIndexMapper.getVisualFromRenderableIndex(topRow);
  }
  if (startColumn === 0) {
    startColumn = columnIndexMapper.getVisualFromRenderableIndex(startColumn);
  }
  if (topRow === null || startColumn === null) {
    return null;
  }
  return hot._createCellCoords(topRow, startColumn);
}

/**
 * Gets the coordinates of the most bottom-end cell or header (depends on the table settings and its size).
 *
 * @param {Core} hot The Handsontable instance.
 * @returns {CellCoords|null}
 */
function getMostBottomEndPosition(hot) {
  var _rowIndexMapper$getVi, _columnIndexMapper$ge;
  const {
    rowIndexMapper,
    columnIndexMapper
  } = hot;
  const {
    navigableHeaders
  } = hot.getSettings();
  let bottomRow = rowIndexMapper.getRenderableIndexesLength() - 1;
  let endColumn = columnIndexMapper.getRenderableIndexesLength() - 1;
  if (bottomRow < 0) {
    if (!navigableHeaders || hot.countColHeaders() === 0) {
      return null;
    }
    bottomRow = -1;
  }
  if (endColumn < 0) {
    if (!navigableHeaders || hot.countColHeaders() === 0) {
      return null;
    }
    endColumn = -1;
  }
  return hot._createCellCoords((_rowIndexMapper$getVi = rowIndexMapper.getVisualFromRenderableIndex(bottomRow)) !== null && _rowIndexMapper$getVi !== void 0 ? _rowIndexMapper$getVi : bottomRow, (_columnIndexMapper$ge = columnIndexMapper.getVisualFromRenderableIndex(endColumn)) !== null && _columnIndexMapper$ge !== void 0 ? _columnIndexMapper$ge : endColumn);
}