import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
import { Grammar } from "./grammar.js";

class Migration {
  get code() { return "sample"; }
  get version() { return "0.0.0"; }
  async migrate() { }

  async applyItemsUpdates(computeUpdates) {
    await game.actors.forEach(async (actor) => {
      const actorItemUpdates = computeUpdates(actor.items);
      if (actorItemUpdates.length > 0) {
        console.log(
          this.code,
          `Applying updates on actor ${actor.name} items`,
          actorItemUpdates
        );
        await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
      }
    });

    const itemUpdates = computeUpdates(game.items);
    if (itemUpdates.length > 0) {
      console.log(this.code, "Applying updates on items", itemUpdates);
      await Item.updateDocuments(itemUpdates);
    }
  }

}

class _10_0_16_MigrationSortsReserve extends Migration {
  get code() { return "creation-item-sort-reserve"; }
  get version() { return "10.0.16"; }

  async migrate() {
    await game.actors
      .filter((actor) => actor.type == "personnage")
      .filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0)
      .forEach(async (actor) => {
        const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
        console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
        await actor.createEmbeddedDocuments("Item", sortsReserve, {
          renderSheet: false,
        });
        await actor.update({ 'system.reve.reserve.list': [] })
      });
  }

  conversionSortReserve(it) {
    return {
      type: 'sortreserve',
      name: it.sort.name,
      img: it.sort.img,
      system: {
        // ATTENTION, utilisation de data / _id possibles, encore présents pour les anciens sorts en réserve
        sortid: it.sort._id,
        draconic: it.sort.draconic,
        ptreve: (it.sort.system ?? it.sort.data).ptreve_reel,
        coord: it.coord,
        heurecible: 'Vaisseau',
      },
    };
  }
}

class _10_0_17_MigrationCompetenceCreature extends Migration {
  get code() { return "competences-creature-parade"; }
  get version() { return "10.0.17"; }

  async migrate() {
    await this.applyItemsUpdates(items => items
      .filter(it => it.type == "competencecreature" && it.system.isparade && it.system.categorie_parade == "")
      .map(it => { return { _id: it.id, "system.categorie_parade": "armes-naturelles" } }));

    await this.applyItemsUpdates(items => items
      .filter(it => it.type == "competencecreature" && it.system.iscombat)
      .map(it => { return { _id: it.id, "system.categorie": (Grammar.includesLowerCaseNoAccent(it.name, "lancee") ? "lancer" : "melee") } })
    );

  }
}

class _10_0_21_VehiculeStructureResistanceMax extends Migration {
  get code() { return "vehicule-structure-resistance-max"; }
  get version() { return "10.0.21"; }

  async migrate() {
    await game.actors
      .filter((actor) => actor.type == "vehicule")
      .forEach(async (actor) => {
        await actor.update({
          'system.etat.resistance.value': actor.system.resistance,
          'system.etat.resistance.max': actor.system.resistance,
          'system.etat.structure.value': actor.system.structure,
          'system.etat.structure.max': actor.system.structure
        })
      });
  }
}

export class Migrations {
  static getMigrations() {
    return [
      new _10_0_16_MigrationSortsReserve(),
      new _10_0_17_MigrationCompetenceCreature(),
      new _10_0_21_VehiculeStructureResistanceMax(),
    ];
  }

  constructor() {
    game.settings.register(SYSTEM_RDD, "systemMigrationVersion", {
      name: "System Migration Version",
      scope: "world",
      config: false,
      type: String,
      default: "0.0.0",
    });
  }

  migrate() {
    const currentVersion = game.settings.get(
      SYSTEM_RDD,
      "systemMigrationVersion"
    );
    if (isNewerVersion(game.system.version, currentVersion)) {
      const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
      if (migrations.length > 0) {
        migrations.sort((a, b) =>
          isNewerVersion(a.version, b.version)
            ? 1
            : isNewerVersion(b.version, a.version)
              ? -1
              : 0
        );
        migrations.forEach(async (m) => {
          ui.notifications.info(
            `Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
          );
          await m.migrate();
        });
        ui.notifications.info(
          `Migrations done, version will change to ${game.system.version}`
        );
      } else {
        console.log(
          LOG_HEAD +
          `No migration needeed, version will change to ${game.system.version}`
        );
      }

      game.settings.set(
        SYSTEM_RDD,
        "systemMigrationVersion",
        game.system.version
      );
    } else {
      console.log(LOG_HEAD + `No system version changed`);
    }
  }
}