#pragma once

#include <QRect>
#include <QWidget>

#include "DebrisSelectionChangedEvent.h"
#include "DebugDrawToggledEvent.h"
#include "EntitySelectionChangedEvent.h"
#include "EventHandler.h"
#include "PlayerCommandsAppliedEvent.h"
#include "SelectionChangedEvent.h"
#include "TickAdvancedEvent.h"
#include "selection/SelectionContentFactory.h"
#include "selection/SelectionContext.h"

struct GameConfig;
struct VisualsConfig;
class BuildingIconCache;
class ItemIconCache;
class SelectionContent;
class Simulation;
class QScrollArea;
class QVBoxLayout;

// Shows the current selection. The panel itself renders nothing: it arbitrates between
// the two selection categories (REQ-UI-SELECTION-CATEGORIES), picks the card that fits
// what is selected (REQ-UI-SELECTION-CONTENT), and hosts exactly one of them at a time.
// What each card looks like lives in src/ui/selection/.
//
// The panel floats over the game world view rather than occupying a column of its own
// (REQ-UI-SELECTION-PANEL): it sizes itself to its card, anchors to the right edge of
// the band its owner hands it, and hides itself entirely while nothing is selected
// (REQ-UI-EMPTY-SELECTION).
class SelectionPanel : public QWidget,
                       public CombinedEventHandler<TickAdvancedEvent,
                                                   PlayerCommandsAppliedEvent,
                                                   EntitySelectionChangedEvent,
                                                   SelectionChangedEvent,
                                                   DebrisSelectionChangedEvent,
                                                   DebugDrawToggledEvent>
{
    Q_OBJECT

public:
    // visuals, itemIcons and buildingIcons are window-wide rendering resources the cards
    // draw from; none is owned and all must outlive this widget.
    SelectionPanel(Simulation* sim, const GameConfig* config,
                   const VisualsConfig* visuals, ItemIconCache* itemIcons,
                   BuildingIconCache* buildingIcons, QWidget* parent = nullptr);
    ~SelectionPanel() override;

    // Confines the panel to the given band of the game world view: it right-aligns
    // within it and centers vertically in it. The band is the world view less the strip
    // the build button bar occupies, so the two never overlap and the bar never has to
    // move (REQ-UI-SELECTION-PANEL, REQ-UI-BUILD-BAR).
    void anchorTo(const QRect& bandRect);

private:
    void handleEvent(std::shared_ptr<const SelectionChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const EntitySelectionChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const DebrisSelectionChangedEvent> event) override;
    void handleEvent(std::shared_ptr<const TickAdvancedEvent> event) override;
    void handleEvent(std::shared_ptr<const PlayerCommandsAppliedEvent> event) override;
    void handleEvent(std::shared_ptr<const DebugDrawToggledEvent> event) override;

    // Re-reads the live values of the card on screen. When the selection now calls for a
    // different card -- a construction site finishing is the case that matters -- it
    // rebuilds instead, because a card never changes its own shape.
    void refreshContent();
    // Replaces the card with the one the current selection calls for.
    void rebuildContent();
    // Shows the panel while a card exists and hides it otherwise
    // (REQ-UI-EMPTY-SELECTION), re-fitting it to the card while it is shown.
    void updateVisibility();
    // Re-fits the panel to its card within the anchored band.
    void refit();

    SelectionContext m_context;
    // Read through m_context by the cards that need it, so a toggle reaches the card on
    // screen without it having to subscribe to the event itself.
    bool m_debugDrawEnabled = false;

    SelectionRequest  m_request;
    ContentKey        m_contentKey;
    SelectionContent* m_content = nullptr;

    // The band the panel confines itself to, in the coordinates of its parent; null
    // until the owner has anchored it for the first time.
    QRect m_bandRect;

    // Scrolls the card once it outgrows the band (REQ-UI-SELECTION-PANEL). The card is a
    // child of m_body, not of the panel itself.
    QScrollArea* m_scrollArea;
    QWidget*     m_body;
    QVBoxLayout* m_bodyLayout;
};
