#ifndef SDLGRAPHICSPROGRAM
#define SDLGRAPHICSPROGRAM

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <vector>

#include "imgui.h"

#include "GameObject.hpp"
#include "IGraphicsEngineRenderer.hpp"
#include "PhysicsEngine.hpp"
#include "GameMakerGUI.hpp"

/**
 * The main game engine class.
 * Holds all objects relevant to the game and runs them based on a clock.
 */
class Engine
{
public:
    /**
     * Constructor of Engine
     */
    Engine();

    /**
     * Destructor
     */
    ~Engine();

    /**
     * Gets user input
     * @param
     */
    void Input(bool *quit, bool *editing);

    /**
     * Per frame update
     */
    void Update();

    /**
     * Per frame render. Renders everything
     */
    void Render();

    /**
     * Main Game Loop that runs forever
     */
    void MainGameLoop();

    /**
     * Initialization and shutdown pattern.
     * Explicitly call 'Start' to launch the engine
     */
    void Start();

    /**
     * Initialization and shutdown pattern.
     * Explicitly call 'Shutdown' to terminate the engine
     */
    void Shutdown();

    /**
     * Request to startup the Graphics Subsystem.
     * @see IGraphicsEngineRenderer
     */
    void InitializeGraphicsSubSystem();

    /**
     * Request to startup the Physics Subsystem.
     * @see PhysicsEngine
     */
    void InitializePhysicsSubsystem();

    /**
     * Request to startup the GUI Subsystem.
     * @see GameMakerGUI
     */
    void InitializeGUI();

    /**
     * Create a new bespoke Fly GameObject at the given location.
     * Used to create the demo scene.
     *
     * @param player the position of the player
     * @param spawnPos the position to place the new GameObject
     * @return a Fly GameObject
     */
    GameObject *createFly(TransformComponent *player, Vec2D spawnPos);

private:
    /**
     * Object that renders all objects
     */
    SDLGraphicsEngineRenderer *mRenderer = nullptr;

    /**
     * Calculates all collisions
     */
    PhysicsEngine *mPhysics = nullptr;

    /**
     * Displays editor
     */
    GameMakerGUI *mGUI = nullptr;

    /**
     * Holds all game objects
     */
    std::vector<GameObject *> m_gameobjects;

    bool runGame = true; /**< Used to pause/play the game */
};

#endif
