/******************************************************************************
*	File		-	core.h
*	Author		-	Joey Pollack
*	Date		-	2021/08/30 (y/m/d)
*	Mod Date	-	2021/08/30 (y/m/d)
*	Description	-	The Core Engine Class. Manages the engine components.
******************************************************************************/

#ifndef CORE_H_
#define CORE_H_

#include "common_defs.h"
#include "state.h"
#include "run_mode.h"
#include <gui/panel.h>
#include <gui/panel_defs.h>
#include <utils/logger.h>
#include <utils/args.h>
#include <utils/frame_counter.h>

namespace lunarium
{

    class Image;
    class TestBed;
    class GUI;
    class IGraphics;
    class Window;
    class InputManager;

    class Core
    {
    public:
        static Core& GetInstance();
        static void Shutdown();

        void Initialize(int argc, char** argv);
        void SignalShutdown();

        bool IsInit() const;
        const State& GetState() const;

        void ApplyState(State newState);

        void RunGameLoop();

        OpRes BeginRenderToTexture(int id);
        Image* EndRenderToTexture();


    private:    // DATA
        static Core* mpInstance;
        bool mbIsInit;
        State mState;
        Args* mpArgs;
        FrameCounter mFrameCounter;
        iRunMode* mpRunMode;
        bool mbMidRender;
        bool mbMidTextureRender;
        bool mbShowGuiDemo;

        // Panels
        struct
        {
            uint32_t CoreConsole;
        } mPanelIDs;
        std::vector<gui::Panel*> mPanels;

		// Log Files
		std::ofstream mMasterLogFile;
		std::ofstream mErrorLogFile;
		std::ofstream mGraphicsLogFile;

    private: // SUBSYSTEMS

    Window*         mpWindow;
    IGraphics*      mpGraphics;
    InputManager*   mpInput;
    GUI&            mGUI;

    public:    // SUBSYSTEM GETTERS
        
		static Window& MainWindow();
        static IGraphics& Graphics();
        static InputManager& Input();

    private: // HELPERS
        uint32_t AddPanel(gui::Panel* p);
        void FreePanel(uint32_t id);

    private: // HIDDEN METHODS

        Core();
        Core(const Core&) = delete;
        Core& operator=(const Core&) = delete;

    private: // RUN MODES
        TestBed* mpTester;
    };


    class CoreLogListener : public LogListener
	{
	public:
		CoreLogListener(u32 acceptedLogLevels = LogLevel::ANY,
			u32 acceptedLogCategories = LogCategory::ANY, const char* myName = "CoreLogListener");
		bool Log(LogMessage& message);
	};

}

#endif  // CORE_H_