// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT

import {
  getSceneMigrator,
  migrateCollection,
  migrateCompendiums,
  getCompendiumMigrator,
  getActorMigrator,
} from "./migrationHelpers.js";

const secondsPerRound = 5;
const secondsPerMinute = 60;
const roundsPerMinute = secondsPerMinute / secondsPerRound;
const minutesPerHour = 60;
const roundsPerHour = minutesPerHour / roundsPerMinute;
const hoursPerDay = 24;
const roundsPerDay = hoursPerDay / roundsPerHour;
const secondsPerDay = secondsPerMinute * minutesPerHour * hoursPerDay;

/** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() {
  const itemsResult = await migrateCollection(game.items, migrateItem);
  const actorsResult = await migrateCollection(game.actors, migrateActor);
  const scenesResult = await migrateCollection(game.scenes, migrateScene);
  const compendiumsResult = await migrateCompendiums(migrateCompendium);
  return itemsResult === "error" ||
    actorsResult === "error" ||
    scenesResult === "error" ||
    compendiumsResult === "error"
    ? "error"
    : "success";
}

/** @type {import('./migrationHelpers.js').Migrator<Item>} */
async function migrateItem(item) {
  if (item.type === "spell") {
    const cooldownDurationUnit = item.system?.cooldownDuration.unit;
    const cooldownDurationValue = item.system?.cooldownDuration.value;
    const cooldownDuration = migrateCooldownDuration(cooldownDurationValue, cooldownDurationUnit);
    await item.update({ system: { cooldownDuration } });
  }
}

function migrateCooldownDuration(cooldownDurationValue = "", cooldownDurationUnit = "") {
  if (Number.isNumeric(cooldownDurationValue)) {
    const value = Number.fromString(cooldownDurationValue);
    const rounds = getRounds(cooldownDurationUnit, value);

    if (rounds * secondsPerRound > secondsPerDay) {
      return "d20d";
    } else if (rounds > 100) {
      return "1d";
    } else if (rounds > 10) {
      return "100r";
    } else if (rounds > 5) {
      return "10r";
    } else if (rounds > 2) {
      return "5r";
    } else if (rounds > 1) {
      return "2r";
    } else if (rounds > 0) {
      return "1r";
    } else {
      return "0r";
    }
  } else {
    // if the value is not numeric, we can only make a best guess
    switch (cooldownDurationUnit) {
      case "rounds": {
        return "10r";
      }
      case "minutes": {
        return "100r";
      }
      case "hours": {
        return "1d";
      }
      case "days": {
        return "d20d";
      }
      default: {
        return "0r";
      }
    }
  }
}

/**
 * Given a unit and a value, return the correct number of rounds
 * @param {string} unit     The unit
 * @param {number} value    The value
 * @returns {number} The number of rounds
 */
function getRounds(unit, value) {
  switch (unit) {
    case "rounds": {
      return value;
    }
    case "minutes": {
      return value * roundsPerMinute;
    }
    case "hours": {
      return value * roundsPerHour;
    }
    case "days": {
      return value * roundsPerDay;
    }
    default: {
      return 0;
    }
  }
}

const migrateActor = getActorMigrator(migrateItem);
const migrateScene = getSceneMigrator(migrateActor);
const migrateCompendium = getCompendiumMigrator({ migrateItem, migrateActor, migrateScene });

/** @type {import("./migration.js").Migration} */
export const migration = {
  migrate,
  migrateCompendium,
};
