#include <Milestone/BrickByBrickMilestone/BrickByBrickMilestone.hpp>
#include <Milestone/DiggingDeeperMilestone/DiggingDeeperMilestone.hpp>
#include <Milestone/DripMilestone/DripMilestone.hpp>
#include <Milestone/ElectronicsMilestone/ElectronicsMilestone.hpp>
#include <Milestone/FossilFuelsMilestone/FossilFuelsMilestone.hpp>
#include <Milestone/HydraulicsMilestone/HydraulicsMilestone.hpp>
#include <Milestone/IndustrialRevolutionMilestone/IndustrialRevolutionMilestone.hpp>
#include <Milestone/MetalWorkingMilestone/MetalWorkingMilestone.hpp>
#include <MilestoneRegistry/MilestoneRegistry.hpp>
#include <Milestone/StoneAgeMilestone/StoneAgeMilestone.hpp>
#include <Milestone/CarpentryMilestone/CarpentryMilestone.hpp>
#include <Milestone/BronzeAgeMilestone/BronzeAgeMilestone.hpp>
#include <Milestone/NavigationMilestone/NavigationMilestone.hpp>

MilestoneRegistry milestoneRegistry;

MilestoneRegistry::MilestoneRegistry() {}

void MilestoneRegistry::registerAllMilestones()
{
    registerMilestone<StoneAgeMilestone>();
    registerMilestone<CarpentryMilestone>();
    registerMilestone<BronzeAgeMilestone>();
    registerMilestone<NavigationMilestone>();
    registerMilestone<MetalWorkingMilestone>();
    registerMilestone<BrickByBrickMilestone>();
    registerMilestone<ElectronicsMilestone>();
    registerMilestone<HydraulicsMilestone>();
    registerMilestone<FossilFuelsMilestone>();
    registerMilestone<DripMilestone>();
    registerMilestone<DiggingDeeperMilestone>();
    registerMilestone<IndustrialRevolutionMilestone>();

    std::vector<std::string> ids;
    for (const auto &[id, milestone] : milestones)
    {
        ids.push_back(id);
    }
}

Milestone& MilestoneRegistry::getMilestone(const std::string &milestoneId)
{
    return *milestones[milestoneId];
}

void MilestoneRegistry::getSortedMilestoneList(std::vector<Milestone*> &sortedList)
{
    for (const auto &[_, milestone] : milestones)
    {
        sortedList.push_back(milestone.get());
    }

    std::sort(sortedList.begin(), sortedList.end(), [](Milestone* a, Milestone* b) {
        return a->label < b->label;
    });
}