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

import {
    getActorUpdateDataGetter,
    getCompendiumMigrator,
    getSceneUpdateDataGetter,
    migrateActors,
    migrateCompendiums,
    migrateItems,
    migrateScenes,
} from "./migrationHelpers";

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;

async function migrate(): Promise<void> {
    await migrateItems(getItemUpdateData);
    await migrateActors(getActorUpdateData);
    await migrateScenes(getSceneUpdateData);
    await migrateCompendiums(migrateCompendium);
}

function getItemUpdateData(itemData: Partial<foundry.data.ItemData["_source"]>) {
    if (itemData.type !== "spell") return;
    // @ts-expect-error the type of cooldownDuration is changed from UnitData<TemporalUnit> to CooldownDuation with this migration
    const cooldownDurationUnit: string | undefined = itemData.data?.cooldownDuration.unit;
    // @ts-expect-error the type of cooldownDuration is changed from UnitData<TemporalUnit> to CooldownDuation with this migration
    const cooldownDurationValue: string | undefined = itemData.data?.cooldownDuration.value;
    const cooldownDuration = migrateCooldownDuration(cooldownDurationValue, cooldownDurationUnit);

    const updateData: Record<string, unknown> = {
        data: {
            cooldownDuration,
        },
    };
    return updateData;
}

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";
            }
        }
    }
}

function getRounds(unit: string, value: number): number {
    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 getActorUpdateData = getActorUpdateDataGetter(getItemUpdateData);
const getSceneUpdateData = getSceneUpdateDataGetter(getActorUpdateData);
const migrateCompendium = getCompendiumMigrator({ getItemUpdateData, getActorUpdateData, getSceneUpdateData });

export const migration = {
    migrate,
    migrateCompendium,
};