#ifndef WORLD_MIGRATOR_HPP_
#define WORLD_MIGRATOR_HPP_

#include <AtomicDataStore/AtomicDataStore.hpp>
#include <functional>

class WorldMigrator final
{
private:
    typedef std::function<bool(WorldMigrator &wm)> MigrationCallback;

    struct Migration
    {
        Version sourceVersion;
        MigrationCallback migrate;
    };

    typedef std::vector<Migration>::iterator MigrationIterator;

    AtomicDataStore &store;
    AtomicDataStore::Plan &plan;
    MigrationIterator initialMigration;
    std::string error;

    static std::vector<Migration> migrations;

    /**
     * @brief Returns a reference to file content.
     *
     * The file will be read from the store if it's not already in the plan. If it does
     * not exist, it will be initialized as empty. You can modify the content to include it
     * in the migration plan.
     */
    std::vector<uint8_t>& getFile(const std::string &path);

    static void addMigration(Version sourceVersion, MigrationCallback migrate);

public:
    WorldMigrator(AtomicDataStore &store, AtomicDataStore::Plan &plan);

    void migrate();
    const std::string& getError();

    static void initMigrations();
};

#endif