#pragma once
#include <cstdint>
#include <imgui.h>

#include "Gen.h"

namespace Puzzle
{
    using namespace Generated;

    constexpr const char* PuzzleFileDir = "game/data/puzzles/";

    struct Config
    {
        static constexpr uint32_t CardSize = 2;
        static constexpr uint32_t NodesPerCard = CardSize * CardSize;
        static constexpr uint32_t MaxElementsPerTile = 4;
        static constexpr uint32_t MaxPuzzleSizeCards = 16;
        static constexpr uint32_t MaxCardsInPuzzle = MaxPuzzleSizeCards * MaxPuzzleSizeCards;
        static constexpr uint32_t MaxPuzzleSizeTiles = 16 * CardSize;
        static constexpr uint32_t MaxTilesInPuzzle = MaxPuzzleSizeTiles * MaxPuzzleSizeTiles;
        static constexpr uint32_t MaxAvailableStacks = 16;
        static constexpr uint32_t MaxGoalPositions = 16;
        static constexpr float CardScaleWorld = 10.0f;
    };

    void Setup();
    StaticPuzzleData& GetStaticPuzzleData();
    void LoadStaticPuzzleData();
    void SaveStaticPuzzleData();
    const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H);
    bool IsValid(StaticPuzzleCardHandle h);
    uint8_t GetRemainingCount(const PuzzleCardStack& stack);
    PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos);
    PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y);
    PuzzleElementType::Enum& EditCardNodeAt(StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y);
    void DrawCard(const StaticPuzzleCard& card, uint8_t rotation, ImVec2 pos);

    struct PuzzleSolver
    {
        bool IsPuzzleSolved(const Generated::PuzzleData& puzzle);
        bool IsExitSatisfied(const Generated::PuzzleData& puzzle, PuzPos pos);

        // This assumes flowFrom is already verified to be connected.
        bool IsValidGoalConnection(const Generated::PuzzleData& puzzle,
                                   PuzPos flowFrom,
                                   PuzPos flowTo,
                                   PuzzleElementType::Enum goalType);
        bool IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType);
    };
    bool RenderDebugUI(PuzzleData& obj);
} // namespace Puzzle
