"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useSpotlightRestore = exports.useSpotlightConfig = void 0;
var _spotlight = _interopRequireDefault(require("@enact/spotlight"));
var _utilDOM = _interopRequireDefault(require("@enact/ui/useScroll/utilDOM"));
var _react = require("react");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
var useSpotlightConfig = exports.useSpotlightConfig = function useSpotlightConfig(props, instances) {
  // Hooks

  (0, _react.useEffect)(function () {
    function lastFocusedPersist() {
      var lastFocusedIndex = instances.spottable.current.lastFocusedIndex;
      if (lastFocusedIndex != null) {
        return {
          container: false,
          element: true,
          key: lastFocusedIndex
        };
      }
    }
    function lastFocusedRestore(_ref, all) {
      var key = _ref.key;
      var placeholder = all.find(function (el) {
        return 'vlPlaceholder' in el.dataset;
      });
      if (placeholder) {
        placeholder.dataset.index = key;
        return placeholder;
      }
      return all.reduce(function (focused, node) {
        return focused || Number(node.dataset.index) === key && node;
      }, null);
    }
    function configureSpotlight() {
      var spacing = props.spacing,
        spotlightId = props.spotlightId;
      _spotlight["default"].set(spotlightId, {
        enterTo: 'last-focused',
        /*
         * Returns the data-index as the key for last focused
         */
        lastFocusedPersist: lastFocusedPersist,
        /*
         * Restores the data-index into the placeholder if its the only element. Tries to find a
         * matching child otherwise.
         */
        lastFocusedRestore: lastFocusedRestore,
        /*
         * Directs spotlight focus to favor straight elements that are within range of `spacing`
         * over oblique elements, like scroll buttons.
         */
        obliqueMultiplier: spacing > 0 ? spacing : 1
      });
    }
    configureSpotlight();
  }, [props, instances]);
};
var getNumberValue = function getNumberValue(index) {
  // using '+ operator' for string > number conversion based on performance: https://jsperf.com/convert-string-to-number-techniques/7
  var number = +index;
  // should return -1 if index is not a number or a negative value
  return number >= 0 ? number : -1;
};
var useSpotlightRestore = exports.useSpotlightRestore = function useSpotlightRestore(props, instances, context) {
  var scrollContentRef = instances.scrollContentRef,
    spottable = instances.spottable;
  var focusByIndex = context.focusByIndex,
    getItemNode = context.getItemNode;

  // Mutable value

  var mutableRef = (0, _react.useRef)({
    preservedIndex: false,
    lastSpotlightDirection: null,
    restoreLastFocused: false
  });

  // Hooks

  (0, _react.useEffect)(restoreFocus);

  // Functions

  function handlePlaceholderFocus(ev) {
    var placeholder = ev.currentTarget;
    if (placeholder) {
      var index = placeholder.dataset.index;
      if (index) {
        mutableRef.current.preservedIndex = getNumberValue(index);
        mutableRef.current.lastSpotlightDirection = null;
        mutableRef.current.restoreLastFocused = true;
      }
    }
  }
  function isPlaceholderFocused() {
    var current = _spotlight["default"].getCurrent();
    if (current && current.dataset.vlPlaceholder && _utilDOM["default"].containsDangerously(scrollContentRef.current, current)) {
      return true;
    }
    return false;
  }
  function restoreFocus() {
    if (mutableRef.current.restoreLastFocused && !isPlaceholderFocused()) {
      var spotlightId = props.spotlightId,
        itemNode = getItemNode(mutableRef.current.preservedIndex);
      if (itemNode) {
        // if we're supposed to restore focus and virtual list has positioned a set of items
        // that includes lastFocusedIndex, clear the indicator
        mutableRef.current.restoreLastFocused = false;

        // try to focus the last focused item
        spottable.current.isScrolledByJump = true;
        var foundLastFocused = focusByIndex(mutableRef.current.preservedIndex, mutableRef.current.lastSpotlightDirection);
        spottable.current.isScrolledByJump = false;

        // but if that fails (because it isn't found or is disabled), focus the container so
        // spotlight isn't lost
        if (!foundLastFocused) {
          mutableRef.current.restoreLastFocused = true;
          _spotlight["default"].focus(spotlightId);
        }
      }
    }
  }
  function handleRestoreLastFocus(_ref2) {
    var firstIndex = _ref2.firstIndex,
      lastIndex = _ref2.lastIndex;
    if (mutableRef.current.restoreLastFocused && mutableRef.current.preservedIndex >= firstIndex && mutableRef.current.preservedIndex <= lastIndex) {
      restoreFocus();
    }
  }
  function updateStatesAndBounds(_ref3) {
    var dataSize = _ref3.dataSize,
      moreInfo = _ref3.moreInfo,
      numOfItems = _ref3.numOfItems;
    return mutableRef.current.restoreLastFocused && numOfItems > 0 && mutableRef.current.preservedIndex < dataSize && (mutableRef.current.preservedIndex < moreInfo.firstVisibleIndex || mutableRef.current.preservedIndex > moreInfo.lastVisibleIndex);
  }
  function setPreservedIndex(index) {
    var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
    mutableRef.current.preservedIndex = index;
    mutableRef.current.lastSpotlightDirection = direction;
    mutableRef.current.restoreLastFocused = true;
  }

  // Return

  return {
    handlePlaceholderFocus: handlePlaceholderFocus,
    handleRestoreLastFocus: handleRestoreLastFocus,
    setPreservedIndex: setPreservedIndex,
    updateStatesAndBounds: updateStatesAndBounds
  };
};