#pragma once

#include <optional>
#include <vector>

#include <QWidget>

#include "Blueprint.h"
#include "BlueprintModeExitedEvent.h"
#include "BuildingBlocksChangedEvent.h"
#include "BuildingId.h"
#include "EventHandler.h"
#include "GameConfig.h"
#include "SelectionChangedEvent.h"
#include "TemporaryBlueprintRequestedEvent.h"
#include "Tick.h"

class Simulation;
class QPushButton;
class QScrollArea;
class QVBoxLayout;

class BlueprintPanel : public QWidget,
                       public CombinedEventHandler<BuildingBlocksChangedEvent,
                                                   SelectionChangedEvent,
                                                   BlueprintModeExitedEvent,
                                                   TemporaryBlueprintRequestedEvent>
{
    Q_OBJECT

public:
    BlueprintPanel(Simulation* sim, const GameConfig* config, QWidget* parent = nullptr);
    ~BlueprintPanel() override;

private:
    void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const SelectionChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const BlueprintModeExitedEvent> event) override;
    void handleEvent(std::shared_ptr<const TemporaryBlueprintRequestedEvent> event) override;

private slots:
    void onCreateClicked();
    void onDeleteBlueprintClicked(int index);
    void onBlueprintButtonClicked(int index);

private:
    void onSelectionChanged(const std::vector<BuildingId>& ids);
    void clearActiveBlueprintButton();
    Blueprint createBlueprintFromSelection() const;
    int       computeBlueprintCost(const Blueprint& bp) const;
    void      rebuildButtons();
    void      refreshButtonStates();
    void      loadFromDisk();
    void      saveToDisk() const;

    // The simulation is the single source of truth for the block stock; the
    // change event is only a refresh signal.
    Simulation*               m_sim;
    const GameConfig*         m_config;
    std::vector<BuildingId>     m_selectedBuildingIds;
    std::optional<int>        m_activeIndex;  // nullopt = no blueprint selected
    std::vector<Blueprint>    m_blueprints;
    std::vector<QPushButton*> m_blueprintButtons;
    QPushButton*              m_createBtn;
    QWidget*                  m_buttonsContainer;
    QVBoxLayout*              m_buttonsLayout;
};
