#pragma once

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

#include <QPushButton>
#include <QScrollArea>
#include <QTimer>
#include <QWidget>

#include "ArenaInspectRequestedEvent.h"
#include "ArenaStartRequestedEvent.h"
#include "ArenaWidget.h"
#include "ArenaSimulation.h"
#include "BalancingConfig.h"
#include "EventHandler.h"
#include "GameConfig.h"
#include "InspectWindowClosedEvent.h"
#include "VisualsConfig.h"

class InspectWindow;

class BalancingWindow : public QWidget,
                        public CombinedEventHandler<ArenaStartRequestedEvent,
                                                    ArenaInspectRequestedEvent,
                                                    InspectWindowClosedEvent>
{
    Q_OBJECT

public:
    BalancingWindow(const BalancingConfig& balancingConfig,
                    GameConfig gameConfig,
                    const std::string& configDir,
                    const std::string& balancingConfigPath,
                    QWidget* parent = nullptr);
    ~BalancingWindow() override;

private:
    void handleEvent(std::shared_ptr<const ArenaStartRequestedEvent> event) override;
    void handleEvent(std::shared_ptr<const ArenaInspectRequestedEvent> event) override;
    void handleEvent(std::shared_ptr<const InspectWindowClosedEvent> event) override;

private slots:
    void pollStatuses();
    void reloadConfig();
    void startAll();
    void writeLog();

private:
    void startArena(int index);
    void inspectArena(int index);
    void closeInspectWindow();
    void populateArenas(const BalancingConfig& balancingConfig);
    void stopAllArenas();
    void updateButtons();
    void setMainControlsEnabled(bool enabled);

    struct ArenaEntry
    {
        ArenaConfig config;
        std::unique_ptr<ArenaSimulation> simulation;
        std::thread worker;
        ArenaWidget* widget;
    };

    std::vector<ArenaEntry> m_arenas;
    GameConfig m_gameConfig;
    VisualsConfig m_visuals;
    std::string m_configDir;
    std::string m_balancingConfigPath;
    unsigned int m_nextSeed;
    QPushButton* m_reloadButton;
    QPushButton* m_startAllButton;
    QPushButton* m_logButton;
    QScrollArea* m_scrollArea;
    QTimer* m_pollTimer;

    InspectWindow* m_inspectWindow;
    std::optional<int> m_inspectedArenaIndex;  // nullopt = no arena inspected
    std::unique_ptr<ArenaSimulation> m_inspectedSim;
};
