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

import { getGame } from "./helpers";
import logger from "./logger";
import { migration as migration001 } from "./migrations/001";
import { migration as migration002 } from "./migrations/002";
import { migration as migration003 } from "./migrations/003";
import { migration as migration004 } from "./migrations/004";
import { migration as migration005 } from "./migrations/005";
import { migration as migration006 } from "./migrations/006";
import notifications from "./ui/notifications";

async function migrate(): Promise<void> {
    if (!getGame().user?.isGM) {
        return;
    }

    const oldMigrationVersion = getGame().settings.get("ds4", "systemMigrationVersion");

    const targetMigrationVersion = migrations.length;

    if (isFirstWorldStart(oldMigrationVersion)) {
        getGame().settings.set("ds4", "systemMigrationVersion", targetMigrationVersion);
        return;
    }

    return migrateFromTo(oldMigrationVersion, targetMigrationVersion);
}

async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion: number): Promise<void> {
    if (!getGame().user?.isGM) {
        return;
    }

    const migrationsToExecute = migrations.slice(oldMigrationVersion, targetMigrationVersion);

    if (migrationsToExecute.length > 0) {
        notifications.info(
            getGame().i18n.format("DS4.InfoSystemUpdateStart", {
                currentVersion: oldMigrationVersion,
                targetVersion: targetMigrationVersion,
            }),
            { permanent: true },
        );

        for (const [i, { migrate }] of migrationsToExecute.entries()) {
            const currentMigrationVersion = oldMigrationVersion + i + 1;
            logger.info("executing migration script ", currentMigrationVersion);
            try {
                await migrate();
                getGame().settings.set("ds4", "systemMigrationVersion", currentMigrationVersion);
            } catch (err) {
                notifications.error(
                    getGame().i18n.format("DS4.ErrorDuringMigration", {
                        currentVersion: oldMigrationVersion,
                        targetVersion: targetMigrationVersion,
                        migrationVersion: currentMigrationVersion,
                    }),
                    { permanent: true },
                );
                logger.error("Failed ds4 system migration:", err);
                return;
            }
        }

        notifications.info(
            getGame().i18n.format("DS4.InfoSystemUpdateCompleted", {
                currentVersion: oldMigrationVersion,
                targetVersion: targetMigrationVersion,
            }),
            { permanent: true },
        );
    }
}

async function migrateCompendiumFromTo(
    pack: CompendiumCollection<CompendiumCollection.Metadata>,
    oldMigrationVersion: number,
    targetMigrationVersion: number,
): Promise<void> {
    if (!getGame().user?.isGM) {
        return;
    }

    const migrationsToExecute = migrations.slice(oldMigrationVersion, targetMigrationVersion);

    if (migrationsToExecute.length > 0) {
        notifications.info(
            getGame().i18n.format("DS4.InfoCompendiumMigrationStart", {
                pack: pack.title,
                currentVersion: oldMigrationVersion,
                targetVersion: targetMigrationVersion,
            }),
            { permanent: true },
        );

        for (const [i, { migrateCompendium }] of migrationsToExecute.entries()) {
            const currentMigrationVersion = oldMigrationVersion + i + 1;
            logger.info("executing compendium migration ", currentMigrationVersion);
            try {
                await migrateCompendium(pack);
            } catch (err) {
                notifications.error(
                    getGame().i18n.format("DS4.ErrorDuringCompendiumMigration", {
                        pack: pack.title,
                        currentVersion: oldMigrationVersion,
                        targetVersion: targetMigrationVersion,
                        migrationVersion: currentMigrationVersion,
                    }),
                    { permanent: true },
                );
                logger.error("Failed ds4 compendium migration:", err);
                return;
            }
        }

        notifications.info(
            getGame().i18n.format("DS4.InfoCompendiumMigrationCompleted", {
                pack: pack.title,
                currentVersion: oldMigrationVersion,
                targetVersion: targetMigrationVersion,
            }),
            { permanent: true },
        );
    }
}

function getTargetMigrationVersion(): number {
    return migrations.length;
}

interface Migration {
    migrate: () => Promise<void>;
    migrateCompendium: (pack: CompendiumCollection<CompendiumCollection.Metadata>) => Promise<void>;
}

const migrations: Migration[] = [migration001, migration002, migration003, migration004, migration005, migration006];

function isFirstWorldStart(migrationVersion: number): boolean {
    return migrationVersion < 0;
}

export const migration = {
    migrate,
    migrateFromTo,
    getTargetMigrationVersion,
    migrateCompendiumFromTo,
};