//
// Shardok-specific game engine adapter for MCTS
//

#ifndef EAGLE0_SHARDOK_GAME_ENGINE_HPP
#define EAGLE0_SHARDOK_GAME_ENGINE_HPP

#include <functional>
#include <memory>
#include <vector>

#include "src/main/cpp/net/eagle0/common/mcts/abstract/MCTSGameEngine.hpp"
#include "src/main/cpp/net/eagle0/shardok/ai/AIAttackLocations.hpp"
#include "src/main/cpp/net/eagle0/shardok/ai/AIStrategy.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistancesCache.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"

namespace shardok {

// Forward declarations
class AICommandFilter;
class AIScoreCalculator;
class RandomGenerator;

// Use existing type definitions from the Shardok codebase
// GameSettingsSPtr and SettingsGetter are defined in GameSettings.hpp

namespace mcts {

class ShardokGameEngine : public MCTSGameEngine {
public:
    ShardokGameEngine(
            const ShardokEngine* engine,
            const AICommandFilter* commandFilter,
            const AIScoreCalculator* scoreCalculator,
            const GameSettingsSPtr& gameSettings,
            const APDCache* apdCache,
            const ALCache* alCache,
            PlayerId playerId,
            bool isDefender,
            const AIStrategy& strategy,
            const CoordsSet& castleCoords,
            const CoordsSet& criticalTileCoords);

    // MCTSGameEngine interface implementation
    [[nodiscard]] std::unique_ptr<MCTSGameState> applyAction(
            const MCTSGameState& state,
            const MCTSAction& action) const override;

    void applyActionMutable(std::unique_ptr<MCTSGameState>& state, const MCTSAction& action)
            const override;

    [[nodiscard]] std::vector<std::unique_ptr<MCTSAction>> getLegalActions(
            const MCTSGameState& state) const override;

    [[nodiscard]] bool isTerminal(const MCTSGameState& state) const override;

    [[nodiscard]] double evaluateState(const MCTSGameState& state, MCTSPlayerId playerId)
            const override;

    [[nodiscard]] std::vector<size_t> filterActions(
            const std::vector<std::unique_ptr<MCTSAction>>& actions,
            const MCTSGameState& state) const override;

    [[nodiscard]] double getActionScore(
            const MCTSGameState& state,
            const MCTSAction& action,
            MCTSPlayerId playerId) const override;

    [[nodiscard]] bool shouldStopSearch(
            const MCTSGameState& state,
            int iterations,
            std::chrono::steady_clock::time_point startTime) const override;

    [[nodiscard]] size_t mapFilteredIndexToOriginal(
            size_t filteredIndex,
            const MCTSGameState& state) const override;

private:
    const AICommandFilter* commandFilter_;
    const AIScoreCalculator* scoreCalculator_;
    GameSettingsSPtr gameSettings_;
    const APDCache* apdCache_;
    const ALCache* alCache_;
    PlayerId playerId_;
    bool isDefender_;
    AIStrategy strategy_;
    const CoordsSet& castleCoords_;
    // Computed once to avoid 8.5% overhead per engine construction
    const CoordsSet& criticalTileCoords_;
};

}  // namespace mcts
}  // namespace shardok

#endif  // EAGLE0_SHARDOK_GAME_ENGINE_HPP