#pragma once

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include <QWidget>

#include "BuilderModeExitedEvent.h"
#include "BuildHotkeyPressedEvent.h"
#include "BuildingBlocksChangedEvent.h"
#include "BuildingType.h"
#include "DeconstructModeChangedEvent.h"
#include "EventHandler.h"
#include "GameConfig.h"
#include "UnlockedBuildingsChangedEvent.h"

class QPushButton;
class Simulation;
class ItemIconCache;

class BuildButtonGrid : public QWidget,
                        public CombinedEventHandler<BuilderModeExitedEvent,
                                                    DeconstructModeChangedEvent,
                                                    BuildHotkeyPressedEvent,
                                                    BuildingBlocksChangedEvent,
                                                    UnlockedBuildingsChangedEvent>
{
    Q_OBJECT

public:
    // iconDir is the directory holding the per-building "<id>.svg" chip icons
    // (REQ-UI-BUILD-GRID), read from disk at runtime like the config files.
    // itemIcons is the window-wide per-item icon cache and supplies the
    // building_block icon shown in each button's cost (REQ-UI-BUILD-COST). Not
    // owned; must outlive this widget.
    BuildButtonGrid(Simulation* sim, const GameConfig* config,
                    const std::string& iconDir, ItemIconCache* itemIcons,
                    QWidget* parent = nullptr);
    ~BuildButtonGrid() override;

    void clearActiveButton();

private:
    // Re-evaluates which build buttons are enabled from the current building block
    // stock (read from the simulation). If the currently selected tool can no longer
    // be afforded, it exits builder mode so the button does not stay selected.
    void updateAffordability();

    // Re-evaluates which build buttons are visible from the current per-building
    // unlock state (REQ-LOCK-BUILDING); a locked building type's button is hidden.
    void updateVisibility();

    void handleEvent(std::shared_ptr<const BuilderModeExitedEvent> event) override;
    void handleEvent(std::shared_ptr<const DeconstructModeChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const BuildHotkeyPressedEvent> event) override;
    void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const UnlockedBuildingsChangedEvent> event) override;

private slots:
    void onBuildButton(int index);

private:
    Simulation*                      m_sim;
    const GameConfig*                m_config;
    std::string                      m_iconDir;
    ItemIconCache*                   m_itemIcons;  // Not owned; lives in MainWindow.
    std::vector<BuildingType>        m_types;
    std::vector<QPushButton*>        m_buttons;
    std::map<BuildingType, int>      m_costs;
    std::optional<std::size_t>       m_activeIndex;
    QPushButton*                     m_deconstructButton;
};
