/**
 * External dependencies
 */
import { nanoid } from "nanoid";

/**
 * WordPress dependencies
 */
import { useEffect } from "@wordpress/element";

/**
 * Store ids
 */
const ids = {};

/**
 * Generate unique id
 *
 * @param {String} clientId
 * @param {String} id
 * @param {Boolean} allowDuplicatedId
 * @returns {String}
 */
const maybeUpdateId = (clientId, id, allowDuplicatedId) => {
  if (ids[clientId] ?? "") {
    return false;
  }

  if (!id || (!allowDuplicatedId && Object.values(ids).includes(id))) {
    const newId = nanoid(10);

    setId(clientId, newId);

    return newId;
  } else {
    setId(clientId, id);
  }

  return false;
};

/**
 * Set id for the block
 *
 * @param {String} clientId
 * @param {String} id
 */
const setId = (clientId, id) => {
  ids[clientId] = id;
};

/**
 * Make sure the block has a unique id
 *
 * @param {String} id
 * @param {String} clientId an unique value for this kind of block, it can be the block clientId
 * @param {Function} onUpdateId
 * @param {Boolean} inNeedOfUniqueId
 * @param {Boolean} allowDuplicatedId
 * @returns
 */
export const useUniqueId = (
  id,
  clientId,
  onUpdateId,
  inNeedOfUniqueId = true,
  allowDuplicatedId = false,
) => {
  const newId = inNeedOfUniqueId
    ? maybeUpdateId(clientId, id, allowDuplicatedId)
    : false;

  useEffect(() => {
    if (newId && onUpdateId) {
      // Callback
      onUpdateId(newId);
    }

    return () => setId(clientId, null);
  }, [newId, onUpdateId]);

  return newId ? newId : id;
};
