#include "mainWindow.h"

#include "core/appContext.h"

using namespace std;
using namespace quokka_gfx;
//--------------------------------------------------------------
/* Constructor */
MainWindow::MainWindow(AppContext &appContext, quokka_gfx::Application &app)
  : Window(app, "VolaTile", { .w = 1024, .h = 768 }, SDL_WINDOW_RESIZABLE /*| SDL_WINDOW_MAXIMIZED*/)
  , Node(appContext.eventBus)
  , m_appContext(appContext)
  , m_backgroundLayer(*this)
  , m_controlsLayer(*this)
  , m_pianoRollLayer(*this)
  , m_pianoKeyboardLayer(*this, { .w = 1024, .h = 768 })
{
  // Initialization
  SetMinSize({ .w = 1024, .h = 768 });

  // Retrieve the current size of the window (in pixels)
  Size windowSize;
  SDL_GetWindowSize(m_nativeWindow, &windowSize.w, &windowSize.h);

  // Post initialization
  onResize(windowSize);
}
//--------------------------------------------------------------
/* Handle event */
void MainWindow::OnEvent(SDL_Event *event)
{
  // Handle window resize event
  // SDL_EVENT_WINDOW_EXPOSED
  switch (event->type)
  {
    case SDL_EVENT_WINDOW_RESIZED:
    case SDL_EVENT_WINDOW_EXPOSED:
    {
      Size windowSize;

      // Get the current size of the rendering output (in pixels)
      SDL_GetRenderOutputSize(GetRenderer()->getNativeRenderer(), &windowSize.w, &windowSize.h);

      // Update geometry and layout
      onResize(windowSize);

      // Request a redraw of the window content
      Render();
    }
  }
}
//--------------------------------------------------------------
/* Update the window state */
void MainWindow::Update(const std::chrono::nanoseconds dt)
{
  // Handle input events (e.g., check for ESC key to close the window)
  const auto &inputManager = GetInputManager();
  if (inputManager->isKeyPressed(SDL_SCANCODE_ESCAPE))
    Close();

  if (inputManager->isKeyPressed(SDL_SCANCODE_SPACE))
  {
    SDL_ShowOpenFileDialog([](void *userdata, const char *const *filelist, int filter)
                           {
      if (!filelist || !filelist[0])
        return;
      const auto pThis = static_cast<MainWindow *>(userdata);
      pThis->emit<GenericMessageEvent>(HashMessageType("remote.loadFile"), string(filelist[0])); },
                           this,
                           GetNativeWindow(),
                           nullptr,
                           0,
                           nullptr,
                           false);
  }

  // Update the current music time based on playback state
  m_appContext.player->update();

  // Update the layers state and layout
  m_backgroundLayer.update(dt);
  m_controlsLayer.update(dt);
  m_pianoRollLayer.update(dt);
  m_pianoKeyboardLayer.update(dt);
}
//--------------------------------------------------------------
/* Draw the window content (returns true if the window content was drawn, false otherwise) */
bool MainWindow::Draw()
{
  const auto renderer = GetRenderer();     // Get the renderer instance

  // Clear the window with a black background
  renderer->setDrawColor(Color::Black);
  renderer->clear();

  // Render the layers in the correct Z-order (from back to front)
  m_backgroundLayer.render();
  m_controlsLayer.render();
  m_pianoRollLayer.render();
  m_pianoKeyboardLayer.render();

  return true;
}
//--------------------------------------------------------------
/* Handle window resize event */
void MainWindow::onResize(const Size &newSize)
{
  // The window has been resized, it is necessary to update
  // the visual piano layout to fit the new window size. For
  // simplicity, we will just reinitialize the keys
  m_pianoKeyboardLayer.initKeys(newSize);
}
//--------------------------------------------------------------
