//
// Created by m on 12/3/21.
//

#ifndef RLA_IIPP_ENGINE_HPP
#define RLA_IIPP_ENGINE_HPP
#define FMT_HEADER_ONLY
#include <memory>
#include <chrono>
#include "game/game.hpp"
#include <fmt/format.h>
#include <toml.hpp>
#include <functional>
#include "rendering/renderer.hpp"
#include "input/inputprocessor.hpp"
#define MISSING_GAME_ERROR "Game pointer is null"
#define MISSING_RENDERER_ERROR "Renderer pointer is null"
#define RESOURCE_DIR "assets"
#define CONFIG_DIR "config"
#define DEFAULT_TARGET_FPS 61
#define DEFAULT_WINDOW_WIDTH 800
#define DEFAULT_WINDOW_HEIGHT 600
#define DEFAULT_WINDOW_TITLE "RLEngine"
#define DEFAULT_SHOW_FPS false
#define DEFAULT_FONT_NAME "Consolas-Regular"
#define DEFAULT_FONT_SIZE 12

struct EngineConfig {
    unsigned int target_fps;
    int window_width;
    int window_height;
    bool show_fps;
    std::string window_title;
    TextRenderDetails default_font;
};

class Engine {
public:
    Engine(std::unique_ptr<Game> game, std::unique_ptr<Renderer> renderer,
           std::unique_ptr<InputProcessor> input_processor);
    void start_loop();
    static void load_config(const std::string& path, const std::function<void (toml::table)>& f);

    virtual ~Engine();

private:
    EngineConfig config;
    std::unique_ptr<Game> game = nullptr;
    std::unique_ptr<Renderer> renderer = nullptr;
    std::unique_ptr<InputProcessor> input_processor = nullptr;
    std::chrono::time_point<std::chrono::system_clock> render_fps(std::chrono::time_point<std::chrono::system_clock> end, std::chrono::time_point<std::chrono::system_clock> lastframe);
};

class MissingGameException : public std::exception {
public:
    const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override;
};

class MissingRendererException : public std::exception {
public:
    const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override;
};


#endif //RLA_IIPP_ENGINE_HPP
