//@ts-check

/**
 *
 * Creates exclusive states for an HTML element. These states are added as classes
 * and can be used to drive CSS changes.
 * @param {string[]} allModes A string list of all possible modes. It's advised
 *                            to prepend (`state-` or `mode-` to each for clarity)
 * @param {Element} [element] the element to add the classes to. Defaults to the
 *                            document's body
 */
export const createElementStatusModes = (allModes, element = document.body) => {
  /**
   * @param {any} mode
   * @returns {mode is number}
   */
  const isValidIndex = (mode) =>
    typeof mode === "number" && mode >= 0 && mode < allModes.length;

  /**
   * Sets a status mode (class name) on the element.
   * Pass a falsy value to clear all modes
   * @param {number|null|undefined|false} mode
   */
  const set = (mode = false) => {
    mode = isValidIndex(mode) ? mode : -1;
    const modeClass = allModes[mode];
    if (modeClass && element.classList.contains(modeClass)) {
      return;
    }
    element.classList.remove(...allModes);
    element.classList.add(modeClass);
  };

  /**
   * Verifies which of the given classes is set.
   * @returns {string|undefined} the class if there is one
   */
  const get = () =>
    allModes.find((className) => element.classList.contains(className));

  /**
   * @param {number} state
   */
  const is = (state) =>
    isValidIndex(state) && document.body.classList.contains(allModes[state]);

  return { set, get, is };
};

export default createElementStatusModes;
