#ifndef APPLICATION_HPP
#define APPLICATION_HPP

#include "open_engine/events/application_event.hpp"
#include "open_engine/imgui/imgui_layer.hpp"
#include "open_engine/window/window.hpp"
#include "open_engine/layer_stack.hpp"
#include "open_engine/layer.hpp"

int main(int argc, char **argv);

namespace OpenEngine {

    struct ApplicationCommandLineArgs
    {
        int count = 0;
        char** args = nullptr;

        const char* operator[](int index)
        {
            OE_CORE_ASSERT(index < count, "Index is higher than argument count.");

            return args[index];
        };
    };

    class Application
    {
        public:
            Application(const std::string& name,
                    ApplicationCommandLineArgs& args);
            ~Application();

            virtual void OnEvent(Event& event);

            void QueueLayerPush(Ref<Layer> layer);
            void QueueLayerPop(Ref<Layer> layer);
            void QueueOverlayPush(Ref<Layer> layer);
            void QueueOverlayPop(Ref<Layer> layer);
            ImGuiLayer* GetImGuiLayer() { return imgui_layer.get(); };

            inline static Application& Get() { return *instance; };
            ApplicationCommandLineArgs GetCommandLineArgs() const { return arguments; };

            inline Window& GetWindow() { return *window; };

            void Close();

        private:
            void Run();
            bool OnWindowClose(WindowCloseEvent& event);
            bool OnWindowResize(WindowResizeEvent& event);

        private:
            ApplicationCommandLineArgs arguments;
            const std::string name; 
            std::unique_ptr<Window> window;

            inline static Application* instance;
            bool running = true;

            LayerStack layer_stack;
            Ref<ImGuiLayer> imgui_layer;

            friend int ::main(int argc, char **argv);
    };

    // Is defined by client
    Application* CreateApplication(ApplicationCommandLineArgs args);
}

#endif // APPLICATION_HPP
