#pragma once
#include "Deer/Memory.h"

#ifdef DEER_RENDER
#include "DeerRender/Events/ApplicationEvent.h"
#include "DeerRender/Events/Event.h"
#include "DeerRender/Window.h"
#endif

namespace Deer {
	class ImGuiLayer;
	namespace Core {
		extern int argc;
		extern char** argv;
	}  // namespace Core

	class Timestep {
	   public:
		Timestep(float time = 0.0f) : m_time(time) {}

		float getSeconds() const { return m_time; }
		float getMilliseconds() const { return m_time * 1000; }

	   private:
		float m_time;
	};

	namespace Application_tmp {
		using Function = void(*)();
		using EventFunction = void(*)(Event&);

        extern bool running;

		void run();

		void setTickCallback(Function);
		
#ifdef DEER_RENDER
		void initWindow();
		void shutdownWindow();

		void setRenderCallback(Function);
		void setEventCallback(EventFunction);

		Window& getWindow();
#endif
	}

	class Application {
	   public:
		Application();
		~Application();

		static Application* s_application;

		int run();

		virtual int onInit() { return 0; }
		virtual int onPreInit() { return 0; }
		virtual void onShutdown() {}
		virtual void onUpdate(Timestep delta) {}

	   private:
		bool m_running;
		float m_lastFrameTime = 0.0f;
#ifdef DEER_RENDER
	   public:
		Application(const WindowProps& props = WindowProps());

		virtual void onRender(Timestep delta) {}
		virtual void onImGUI() {}
		virtual void onEvent(Event& event) {}

		Scope<Window> m_window;

	   private:
		Scope<ImGuiLayer> m_imGuiLayer;
		const WindowProps m_windowProps;

		virtual void onEventCallback(Event& e);
		void initializeWindow();
		bool onWindowClose(WindowCloseEvent& e);
#endif
	};

}  // namespace Deer
