#include "Window.h"

#include "../Application.h"

#include <stdexcept>

using namespace std;
using namespace quokka_gfx;
//--------------------------------------------------------------
/* Constructor */
Window::Window(Application &app, const std::string &title, const Size &size, const uint64_t flags)
  : m_appOwner(app)
{
  // Create the native SDL window with the specified title, size, and flags
  m_nativeWindow = SDL_CreateWindow(
    title.data(),                                                 // Window title
    size.w,                                                       // Window w
    size.h,                                                       // Window h
    SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN | flags     // Window flags: High pixel density for better rendering on high-DPI displays
  );
  if (!m_nativeWindow)
    throw runtime_error("Failed to create SDL window: " + string(SDL_GetError()));

  // Create the renderer instance associated with this window
  m_renderer = make_unique<Renderer>(*this);

  // Register the window with the application's WindowManager
  m_appOwner.GetWindowManager()->RegisterWindow(this);
}
//--------------------------------------------------------------
/* Default destructor */
Window::~Window()
{
  if (m_nativeWindow)
    SDL_DestroyWindow(m_nativeWindow);
}
//--------------------------------------------------------------
/* Get the native SDL window */
SDL_Window *Window::GetNativeWindow() const noexcept
{
  return m_nativeWindow;
}
//--------------------------------------------------------------
/* Get the renderer instance */
const Renderer *Window::GetRenderer() const noexcept
{
  return m_renderer.get();
}
//--------------------------------------------------------------
/* Get the InputManager instance */
const InputManager *Window::GetInputManager() const noexcept
{
  return &m_appOwner.m_inputManager;
}
//--------------------------------------------------------------
/* Show or hide the window */
void Window::Show(const bool show) const
{
  if (show)
    SDL_ShowWindow(m_nativeWindow);
  else
    SDL_HideWindow(m_nativeWindow);
}
//--------------------------------------------------------------
/* Hide the window */
void Window::Hide() const
{
  Show(false);
}
//--------------------------------------------------------------
/* Close the window */
void Window::Close()
{
  m_appOwner.GetWindowManager()->CloseWindow(this);
}
//--------------------------------------------------------------
/* Set the minimum size of the window */
void Window::SetMinSize(const Size &size) const
{
  SDL_SetWindowMinimumSize(m_nativeWindow, size.w, size.h);
}
//--------------------------------------------------------------
/* Handle event */
void Window::OnEvent(SDL_Event *event) {}
//--------------------------------------------------------------
/* Update the window state */
void Window::Update(const float dt)
{
  // Nothing to do
}
//--------------------------------------------------------------
/* Draw the window content (returns true if the window content was drawn, false otherwise) */
bool Window::Draw()
{
  return false;
}
//--------------------------------------------------------------
/* Render the window */
void Window::Render()
{
  if (!m_renderer)
    return;

  // Set the drawing color to black and clear the rendering target
  (void)m_renderer->setDrawColor(Color::Black);
  (void)m_renderer->clear();

  // Draw the window content
  Draw();

  // Present the rendered content to the window (swap the back buffer to the front)
  m_renderer->present();
}
//--------------------------------------------------------------
