#ifndef MILESTONE_HPP_
#define MILESTONE_HPP_

#include <Material/Material.hpp>
#include <Utilities/Utilities.hpp>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>

/**
 * @brief Description of a milestone in the achievements panel.
 */
class Milestone
{
public:
    struct Dependency
    {
        std::string milestoneId;
        int achievementId;
    };

    struct Achievement
    {
        Material &todoIcon;
        Material &doneIcon;
        std::string title;
        std::string description;
        std::vector<Dependency> deps;

        bool matchesQuery(const std::string &query);
    };

    std::unordered_map<int, std::unique_ptr<Achievement>> achievements;
    std::vector<int> sortedAchievements;
    uint64_t allAchievementBits = 0;

    Material &todoIcon;
    Material &doneIcon;
    std::string label;
    std::string id;

    Milestone(Material &todoIcon, Material &doneIcon, std::string label);

    virtual ~Milestone() = default;

protected:
    template<typename... TArgs>
    void addAchievement(
        int id,
        Material &todoIcon,
        Material &doneIcon,
        std::string title,
        std::string description,
        TArgs... deps
    )
    {
        sortedAchievements.push_back(id);

        if (id >= 64)
        {
            crash(formatString("Milestone::addAchivement: achievement ID must be less than 64, received $+", id));
        }

        allAchievementBits |= static_cast<uint64_t>(1) << id;

        achievements[id] = std::make_unique<Achievement>(Achievement{
            todoIcon,
            doneIcon,
            title,
            description,
            {deps...}
        });
    }

    friend class MilestoneView;
};

#endif