
#include "Hazel/Core/Application.h"

#include <iostream>
#include <Hazel/Debug/Instrumentor.h>
#include <SDL3/SDL.h>

#include "Hazel/Core/Log.h"
#include "Hazel/Renderer/Renderer.h"


namespace Hazel {

	Application* Application::s_Instance = nullptr;


	Application::Application(const std::string& name, int width, int height)
	{
	HZ_PROFILE_FUNCTION();

		if (s_Instance != nullptr)
		{
			HZ_CORE_ERROR("Application already exists!");
		}
		s_Instance = this;

		m_Window = Window::Create(WindowProps(name, width, height));
		m_Window->SetEventCallback(std::bind(&Application::OnEvent, this, std::placeholders::_1));
		m_Window->SetWindowResizeEventCallback(std::bind(&Application::OnWindowResize, this, std::placeholders::_1));

		Renderer::Init();

		m_imguiLayer = new ImGuiLayer();
		PushOverlay(m_imguiLayer);

		m_Window->SetVSync(true);

	}

	Application::~Application()
	{
	}

	void Application::Run() {
		HZ_PROFILE_FUNCTION();
		while (m_Running)
		{
			HZ_PROFILE_SCOPE("RunLoop");
			float    currentTime = static_cast<float>(SDL_GetTicks());
			TimeStep timestep    = currentTime - m_lastFrameTime;
			m_lastFrameTime      = currentTime;


			if (!m_Minimized)
			{
				{
					HZ_PROFILE_SCOPE("LayerStack OnUpdates");
					for (Layer* layer : m_layerStack)
					{
						layer->OnUpdate(timestep);
					}
				}

				m_imguiLayer->Begin();
				{
					HZ_PROFILE_SCOPE("LayerStack OnImGuiRender");
					for (Layer* layer : m_layerStack)
					{
						layer->OnImGuiRender();
					}
				}
				m_imguiLayer->End();
			}

			m_Window->OnUpdate();
		}
	}

	void Application::OnEvent(SDL_Event& e)
	{
        HZ_PROFILE_FUNCTION();

		for (auto it = m_layerStack.end(); it != m_layerStack.begin();)
		{
			(*--it)->OnEvent(e);
		}


		switch (e.type)
		{
		case SDL_EVENT_QUIT:
			m_Running = false;
			break;
		case SDL_EVENT_WINDOW_MINIMIZED:
			m_Minimized = true;
			break;
		case SDL_EVENT_WINDOW_RESTORED:
			m_Minimized = false;
			break;
		default:
			break;
		}
	}

	void Application::OnWindowResize(SDL_Event& e)
	{
		HZ_PROFILE_FUNCTION();
		m_Minimized = false;
		HZ_CORE_INFO("Resized window:({0}, {1})", m_Window->GetWidth(), m_Window->GetHeight());
		// Renderer::OnWindowResize(m_Window->GetWidth(), m_Window->GetHeight());
	}
	void Application::PushLayer(Layer* layer)
	{
        HZ_PROFILE_FUNCTION();
		m_layerStack.PushLayer(layer);
		layer->OnAttach();
	}

	void Application::PushOverlay(Layer* layer)
	{
        HZ_PROFILE_FUNCTION();
		m_layerStack.PushOverlay(layer);
		layer->OnAttach();
	}

	void Application::Close()
	{
		m_Running = false;
	}
}
