#ifndef CKERNEL_HPP
#define CKERNEL_HPP

#include <memory>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

//#include "../Context/CContext.hpp"
//#include "../Context/Window/CGameWindow.hpp"
//#include "../Context/Window/CLoadingWindow.hpp"

//#include "../Controller/Configuration/CGameConfiguration.hpp"
//#include "../Controller/Configuration/CEngineConfiguration.hpp"

//#include "../Controller/Exception/CExceptionManager.hpp"

//#include "Input/CInput.hpp"
#include "../Scene/CScene.hpp"
//#include "../Model/Node/Components/Graphic/CAbstractRenderer.hpp"
//#include "../Model/Node/Components/CAbstractScript.hpp"
//#include "../Model/Node/Components/Graphic/CCamera.hpp"
//#include "../Model/Graphic/Shader/CShader.hpp"
//#include "Shader/CShadersManager.hpp"
//#include "../Utils/CSerializable.hpp"
//#include <boost/atomic/atomic.hpp>

namespace CosmicCore {

    /**
    * @file CKernel.hpp
    * @brief Central class of the game, handle window and I/O.
    */

    /**
    * @brief Central class of the game, handle window and I/O.
    */
    class CKernel {
    private:
        std::string m_configPath;
        std::string m_gameName;
        // The config.
        //CGameConfiguration m_config;
        //CEngineConfiguration m_engineConfig;

        // The windows.
        //CLoadingWindow m_loadingWindow;
        //CGameWindow m_window;

        // Global game var.
        bool m_finished;
        unsigned int m_deltaTime;

        // The Scenes.
        std::unique_ptr<CScene> m_activeScene;
        //std::map<std::string, CScene*> m_sceneList;

        //CInput m_inputHandler;
        //SDL_GLContext m_GLcontext;
        //bool m_isOriginOfContext;

        //CShadersManager m_shaderManager;

    public:
        /**
        * @brief A pointer to the simulation which is accessible from anywhere.
        */
        //static CKernel* m_kernel;

        /**
        * @brief A pointer to the shader used, accessible from anywhere.
        */
        //static CShader* m_mainShader;

        CKernel() = delete;
        CKernel(std::string name, std::string gameName);

        //CKernel(std::string name, std::string gameName, SDL_Window* window);
        ~CKernel();

        std::string getName() { return m_gameName; };
        //CGameConfiguration* getConfig() { return &m_config; };
        //CEngineConfiguration* getEngineConfig() { return &m_engineConfig; };

        //void addScene(std::shared_ptr<CScene>& scene);
        //void setActiveScene(std::string scene);
        //void setContext(SDL_GLContext context);
        //CScene* getActiveScene();
        //unsigned int getNbScene() { return m_sceneList.size(); };
        //std::map<std::string, CScene*>& getScenes() { return m_sceneList; };

        /*CKeyboard* getKeyboard(void) {
            return m_inputHandler.getKeyboard();
        }*/

        /*CMouse* getMouse(void) {
            return m_inputHandler.getMouse();
        }*/

        unsigned int getDeltatime(void) {
            return m_deltaTime;
        }

        void setDeltatime(unsigned int delta){
            m_deltaTime = delta;
        }

        /*void updateInput(){
            m_inputHandler.updateEvent();
        }*/
        /*CShader* getShader(std::string shader)
        {
            return m_shaderManager.get(shader);
        }*/
        //CGameWindow& getGameWindow(){return m_window;};
        //SDL_GLContext getContext(){return m_GLcontext;};
        //void initGL();
        void start(bool isPreview = false);
        void loop();
        void quit();
        void fullscreen();
        void desktop();
        void focus();

        //nlohmann::json to_json();

        /*static CKernel* from_json(SDL_Window* window, SDL_GLContext context, nlohmann::json& j)
        {
            CKernel* g = new CKernel(j["ProjectName"], j["ProjectName"], window);
            g->setContext(context);
            g->start(true);
            for (nlohmann::json& scene : j["Scenes"])
            {
                g->addScene(CScene::from_json(scene));
            }
            g->setActiveScene(j["ActiveScene"]);
            return g;
        };*/

        /*static CKernel* from_json(nlohmann::json& j)
        {
            CKernel* g = new CKernel(j["ProjectName"], j["ProjectName"]);
            g->initGL();
            for (nlohmann::json& scene : j["Scenes"])
            {
                g->addScene(CScene::from_json(scene));
            }
            g->setActiveScene(j["ActiveScene"]);
            return g;
        };*/
    };

}
#endif