import { migrate as migrate0_1_0 } from "./migrations/0-1-0";

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

    const currentVersion: string = game.settings.get("ds4", "systemMigrationVersion");
    const targetVersion = game.system.data.version;

    if (isFirstWorldStart(currentVersion)) {
        game.settings.set("ds4", "systemMigrationVersion", targetVersion);
        return;
    }

    if (isNewerVersion(targetVersion, currentVersion)) {
        ui.notifications.info(
            game.i18n.format("DS4.InfoSystemUpdateStart", {
                currentVersion: currentVersion,
                targetVersion: targetVersion,
            }),
            { permanent: true },
        );

        const migrationFunctionsToExecute = Object.entries(migrations)
            .filter(([version]) => !isNewerVersion(currentVersion, version)) // currentVersion <= version of migration
            .filter(([version]) => isNewerVersion(targetVersion, version)); // targetVersion > version of migration

        for (const migration of migrationFunctionsToExecute) {
            try {
                await migration[1]();
            } catch (err) {
                ui.notifications.error(
                    game.i18n.format("DS4.ErrorDuringMigration", {
                        currentVersion: currentVersion,
                        targetVersion: targetVersion,
                        migrationVersion: migration[0],
                    }),
                    { permanent: true },
                );
                err.message = `Failed ds4 system migration: ${err.message}`;
                console.error(err);
                return;
            }
        }

        ui.notifications.info(
            game.i18n.format("DS4.InfoSystemUpdateCompleted", {
                currentVersion: currentVersion,
                targetVersion: targetVersion,
            }),
            { permanent: true },
        );
        game.settings.set("ds4", "systemMigrationVersion", targetVersion);
        return;
    }
}

/**
 * The migrations to (potentially) execute when a world is loaded. The key
 * specifies the version number _from_ which is being migrated to the next
 * version.
 *
 * @example
 * Given the migration version numbers "0.0.1", "0.0.2", "0.1.2", "0.4.9", and
 * "0.5.0" an update from version "0.0.2" to "0.5.0" would execute the
 * migrations with version "0.0.2", "0.1.2", and "0.4.9". In particular,
 * migrations of a version lower than the current version or higher or equal to
 * the target version are _not_ executed while all others are.
 */
const migrations: Record<string, () => Promise<void>> = {
    "0.1.0": migrate0_1_0,
};

function isFirstWorldStart(version: string): boolean {
    return version === "";
}