/**
 * @file pageIndexing.ts - Utilities for tracking page index mappings within the Syncfusion PDF viewer.
 * Maintains a Map that correlates current page positions (0-based keys) to their original page indices (0-based values).
 * This enables features like page revert by tracking which original page corresponds to each current position after operations such as move, duplicate, insert, or delete.
 * An `undefined` value indicates a page that has no original counterpart (e.g., a newly inserted or duplicated page).
 */

/**
 * Initializes a new page indices tracking map with sequential keys and values.
 *
 * @param count Number of pages to track indices of
 * @returns New map with sequential entries
 */
export function initializePageIndicesMap(
  count: number
): Map<number, number | undefined> {
  const newMap = new Map<number, number | undefined>();
  for (let i = 0; i < count; i++) {
    newMap.set(i, i);
  }
  return newMap;
}

/**
 * Removes a page index pair from the page indices tracking map.
 *
 * @param existingMap Existing page indices tracking map
 * @param removeIndex Key of index pair being removed
 * @returns Updated map with index pair removed
 */
export function removePageIndexPair(
  existingMap: Map<number, number | undefined>,
  removeIndex: number
): Map<number, number | undefined> {
  if (!existingMap.has(removeIndex)) {
    return existingMap;
  }

  const entries = Array.from(existingMap.values());
  entries.splice(removeIndex, 1);

  const newMap = new Map<number, number | undefined>();
  entries.forEach((value, index) => {
    if (value === undefined) {
      newMap.set(index, undefined);
    } else {
      newMap.set(index, value);
    }
  });
  return newMap;
}

/**
 * Inserts new page index pairs into the page indices tracking map with undefined values.
 *
 * @param existingMap Existing page indices tracking map
 * @param startingIndex Index where new index pairs are being added
 * @param numPairs Number of index pairs being added
 * @returns Updated map with index pairs added
 */
export function insertPageIndexPairs(
  existingMap: Map<number, number | undefined>,
  startingIndex: number,
  numPairs: number
): Map<number, number | undefined> {
  const entries = Array.from(existingMap.values());

  const before = entries.slice(0, startingIndex);
  const after = entries.slice(startingIndex);
  const blanks = Array(numPairs).fill(undefined);

  const newEntries = [...before, ...blanks, ...after];

  const newMap = new Map<number, number | undefined>();
  newEntries.forEach((value, index) => newMap.set(index, value));
  return newMap;
}

/**
 * Swaps page index pairs in the page indices tracking map.
 *
 * @param existingMap Existing page indices tracking map
 * @param indexA Key of first index pair
 * @param indexB Key of second index pair
 * @returns Updated map with page index pairs swapped
 */
export function swapPageIndexPairs(
  existingMap: Map<number, number | undefined>,
  indexA: number,
  indexB: number
): Map<number, number | undefined> {
  if (!existingMap.has(indexA) || !existingMap.has(indexB)) {
    return existingMap;
  }

  const entries = Array.from(existingMap.values());
  [entries[indexA], entries[indexB]] = [entries[indexB], entries[indexA]];

  const newMap = new Map<number, number | undefined>();
  entries.forEach((value, index) => newMap.set(index, value));
  return newMap;
}
