#pragma once

#include <stdint.h>
#include <cassert>
#include <vector>
#include <string>
#include "../../core/flags.hpp"

namespace config::client { struct options; }
namespace state {
struct state;
struct reports;
}
namespace render {

//TODO: rewrite as static with function pointers

/// ImGui interface
class UI {
protected:
    UI();

    std::vector<std::string> texturePacks;
public:
    virtual ~UI();

    /// Retro actions to state
    enum class Actions {
        None = 0,
        FPS = 1 << 0,
        FullScreen = 1 << 1,
        ClearColor = 1 << 2,
        RendererSharders = 1 << 3,
        RendererTextures = 1 << 4,
        World = 1 << 5,
        Camera = 1 << 6,
        Control = 1 << 7,
        FillMode = 1 << 8,
        Message = 1 << 9,
        Transparency = 1 << 10,
    };
    friend inline void operator|=(Actions& a, Actions b) {
        a = static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
    }
    friend inline bool operator&&(Actions a, Actions b) {
        return static_cast<int>(a) & static_cast<int>(b);
    }

    /// Compute UI
    virtual Actions draw(config::client::options&, state::state&, const state::reports&) = 0;

    /// Display UI
    virtual void render() = 0;

    /// Is UI in focus
    static bool IsFocus();

    static _FORCE_INLINE_ UI *Get() {
        assert(sInstance != nullptr && "Uninitialized ui");
        return sInstance;
    }
    static void Unload();

protected:
    Actions draw(config::client::options&, state::state &, const state::reports &, intptr_t aim);

    static UI* sInstance;
};

};
