/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import log from "../../../log";
import arrayIncludes from "../../../utils/array_includes";
import type { IParsedAdaptationType, IParsedManifest } from "../types";

/**
 * Ensure that no two periods, adaptations from the same period and
 * representations from the same adaptation, have the same ID.
 *
 * Log and mutate their ID if not until this is verified.
 *
 * @param {Object} manifest
 */
export default function checkManifestIDs(manifest: IParsedManifest): void {
  const periodIDS: string[] = [];
  manifest.periods.forEach((period) => {
    const periodID = period.id;
    if (arrayIncludes(periodIDS, periodID)) {
      log.warn("utils", "Two periods with the same ID found. Updating.", { periodID });
      const newID = periodID + "-dup";
      period.id = newID;
      checkManifestIDs(manifest);
      periodIDS.push(newID);
    } else {
      periodIDS.push(periodID);
    }
    const { adaptations } = period;
    const adaptationIDs: string[] = [];
    (Object.keys(adaptations) as IParsedAdaptationType[]).forEach((type) => {
      const adaptationsForType = adaptations[type];
      if (adaptationsForType === undefined) {
        return;
      }
      adaptationsForType.forEach((adaptation) => {
        const adaptationID = adaptation.id;
        if (arrayIncludes(adaptationIDs, adaptationID)) {
          log.warn("utils", "Two adaptations with the same ID found. Updating.", {
            adaptationID,
          });
          const newID = adaptationID + "-dup";
          adaptation.id = newID;
          checkManifestIDs(manifest);
          adaptationIDs.push(newID);
        } else {
          adaptationIDs.push(adaptationID);
        }
        const representationIDs: Array<number | string> = [];
        adaptation.representations.forEach((representation) => {
          const representationID = representation.id;
          if (arrayIncludes(representationIDs, representationID)) {
            log.warn("utils", "Two representations with the same ID found. Updating.", {
              representationID,
            });
            const newID = `${representationID}-dup`;
            representation.id = newID;
            checkManifestIDs(manifest);
            representationIDs.push(newID);
          } else {
            representationIDs.push(representationID);
          }
        });
      });
    });
  });
}
