#include "controlsLayer.h"

#include "core/player/playerDefs.h"
#include "gui/mainWindow/mainWindow.h"

#include <quokka_gfx.h>
#include <ranges>

using namespace std;
using namespace quokka_gfx;
//--------------------------------------------------------------
/* Constructor */
ControlsLayer::ControlsLayer(MainWindow &owner)
  : Layer(owner)
{
  init();
}
//--------------------------------------------------------------
/* Update the layer state */
void ControlsLayer::update(std::chrono::nanoseconds dt)
{
  const auto &inputManager  = GetInputManager();
  const auto &mousePosition = inputManager->getMousePosition();

  const auto &mouseDownState    = inputManager->isMouseButtonDown(quokka_gfx::InputManager::MouseButton::Left);
  const auto &mousePressedState = inputManager->isMouseButtonPressed(quokka_gfx::InputManager::MouseButton::Left);

  m_playButtonStyle.isHovered  = false;
  m_pauseButtonStyle.isHovered = false;
  m_stopButtonStyle.isHovered  = false;
  m_playButtonStyle.isPressed  = false;
  m_pauseButtonStyle.isPressed = false;
  m_stopButtonStyle.isPressed  = false;

  if (mousePosition.isInBox(m_playButtonStyle.pos, m_playButtonStyle.size))
  {
    m_playButtonStyle.isHovered = true;
    m_playButtonStyle.isPressed = mouseDownState;
    if (mousePressedState)
      m_owner.emit<GenericMessageEvent>(HashMessageType("remote.setState"), player::Command::Play);
  }
  if (mousePosition.isInBox(m_pauseButtonStyle.pos, m_pauseButtonStyle.size))
  {
    m_pauseButtonStyle.isHovered = true;
    m_pauseButtonStyle.isPressed = mouseDownState;
    if (mousePressedState)
      m_owner.emit<GenericMessageEvent>(HashMessageType("remote.setState"), player::Command::Pause);
  }
  if (mousePosition.isInBox(m_stopButtonStyle.pos, m_stopButtonStyle.size))
  {
    m_stopButtonStyle.isHovered = true;
    m_stopButtonStyle.isPressed = mouseDownState;
    if (mousePressedState)
      m_owner.emit<GenericMessageEvent>(HashMessageType("remote.setState"), player::Command::Stop);
  }
}
//--------------------------------------------------------------
/* Render the layer */
void ControlsLayer::render() const
{
  const auto renderer = GetRenderer();     // Get the renderer instance from the main window

  drawPlayButton(*renderer);
  drawPauseButton(*renderer);
  drawStopButton(*renderer);
}
//--------------------------------------------------------------
void ControlsLayer::init()
{
  // Play button style
  m_playButtonStyle.pos  = { .x = 50.0f, .y = 50.0f };
  m_playButtonStyle.size = { .w = 50.0f, .h = 50.0f };

  // Pause button style
  m_pauseButtonStyle.pos  = { .x = 120.0f, .y = 50.0f };
  m_pauseButtonStyle.size = { .w = 50.0f, .h = 50.0f };

  // Stop button style
  m_stopButtonStyle.pos  = { .x = 190.0f, .y = 50.0f };
  m_stopButtonStyle.size = { .w = 50.0f, .h = 50.0f };
}
//--------------------------------------------------------------
void ControlsLayer::drawPlayButton(const quokka_gfx::Renderer &renderer) const
{

  // 1. Dessiner le fond/contour du bouton
  if (m_playButtonStyle.isHovered || m_playButtonStyle.isPressed)
  {
    renderer.setDrawColor(Color::Blue);
    renderer.fillRect(m_playButtonStyle.pos, m_playButtonStyle.size);
    renderer.setDrawColor(Color::Yellow);
  }
  else
  {
    renderer.setDrawColor(Color::Yellow);
    renderer.drawRect(m_playButtonStyle.pos, m_playButtonStyle.size);
    renderer.setDrawColor(Color::Blue);
  }

  // 2. Dessiner l'icône "Play" (un triangle pointant vers la droite)
  // On définit une marge interne (padding) pour que l'icône ne colle pas aux bords
  float paddingX = m_playButtonStyle.size.w * 0.3f;
  float paddingY = m_playButtonStyle.size.h * 0.25f;

  float startX  = m_playButtonStyle.pos.x + paddingX;
  float endX    = m_playButtonStyle.pos.x + m_playButtonStyle.size.w - paddingX;
  float topY    = m_playButtonStyle.pos.y + paddingY;
  float bottomY = m_playButtonStyle.pos.y + m_playButtonStyle.size.h - paddingY;
  float centerY = m_playButtonStyle.pos.y + (m_playButtonStyle.size.h / 2.0f);

  // N'ayant pas de fillTriangle, on remplit le triangle verticalement colonne par colonne
  // (ou horizontalement de la base vers la pointe)
  float totalWidth = endX - startX;
  if (totalWidth > 0.0f)
  {
    for (float x = startX; x <= endX; x += 1.0f)
    {
      // Interpolation linéaire pour trouver la hauteur haute et basse à l'abscisse x
      float progress       = (x - startX) / totalWidth;
      float currentTopY    = topY + (centerY - topY) * progress;
      float currentBottomY = bottomY - (bottomY - centerY) * progress;

      // On dessine une ligne verticale pour cette colonne du triangle
      renderer.drawLine({ x, currentTopY }, { x, currentBottomY });
    }
  }
}
//--------------------------------------------------------------
void ControlsLayer::drawPauseButton(const quokka_gfx::Renderer &renderer) const
{
  // 1. Dessiner le fond/contour
  if (m_pauseButtonStyle.isHovered || m_pauseButtonStyle.isPressed)
  {
    renderer.setDrawColor(Color::Blue);
    renderer.fillRect(m_pauseButtonStyle.pos, m_pauseButtonStyle.size);
    renderer.setDrawColor(Color::Yellow);
  }
  else
  {
    renderer.setDrawColor(Color::Yellow);
    renderer.drawRect(m_pauseButtonStyle.pos, m_pauseButtonStyle.size);
    renderer.setDrawColor(Color::Blue);
  }

  // 2. Dessiner l'icône "Pause" (deux barres verticales)
  float paddingX = m_pauseButtonStyle.size.w * 0.3f;
  float paddingY = m_pauseButtonStyle.size.h * 0.25f;

  float barWidth = (m_pauseButtonStyle.size.w - (2.0f * paddingX)) * 0.35f;               // Largeur d'une barre
  float gap      = m_pauseButtonStyle.size.w - (2.0f * paddingX) - (2.0f * barWidth);     // Espace central

  quokka_gfx::FSize barSize{ barWidth, m_pauseButtonStyle.size.h - (2.0f * paddingY) };

  // Barre Gauche
  quokka_gfx::FPos leftBarPos{ m_pauseButtonStyle.pos.x + paddingX, m_pauseButtonStyle.pos.y + paddingY };
  renderer.fillRect(leftBarPos, barSize);

  // Barre Droite
  quokka_gfx::FPos rightBarPos{ m_pauseButtonStyle.pos.x + paddingX + barWidth + gap, m_pauseButtonStyle.pos.y + paddingY };
  renderer.fillRect(rightBarPos, barSize);
}
//--------------------------------------------------------------
void ControlsLayer::drawStopButton(const quokka_gfx::Renderer &renderer) const
{
  // 1. Dessiner le fond/contour
  if (m_stopButtonStyle.isHovered || m_stopButtonStyle.isPressed)
  {
    renderer.setDrawColor(Color::Blue);
    renderer.fillRect(m_stopButtonStyle.pos, m_stopButtonStyle.size);
    renderer.setDrawColor(Color::Yellow);
  }
  else
  {
    renderer.setDrawColor(Color::Yellow);
    renderer.drawRect(m_stopButtonStyle.pos, m_stopButtonStyle.size);
    renderer.setDrawColor(Color::Blue);
  }

  // 2. Dessiner l'icône "Reset" (une flèche circulaire ou un carré de stop + flèche)
  // Version rapide et propre pour un lecteur MIDI : Le symbole "Retour au début" / "Skip Back"
  // Composé d'un triangle pointant vers la gauche ACCOLÉ à une barre verticale stable.

  float paddingX = m_stopButtonStyle.size.w * 0.3f;
  float paddingY = m_stopButtonStyle.size.h * 0.25f;

  float startX  = m_stopButtonStyle.pos.x + paddingX;
  float endX    = m_stopButtonStyle.pos.x + m_stopButtonStyle.size.w - paddingX;
  float topY    = m_stopButtonStyle.pos.y + paddingY;
  float bottomY = m_stopButtonStyle.pos.y + m_stopButtonStyle.size.h - paddingY;
  float centerY = m_stopButtonStyle.pos.y + (m_stopButtonStyle.size.h / 2.0f);

  float barWidth = m_stopButtonStyle.size.w * 0.08f;     // Épaisseur de la barre de butée

  // A. Dessin de la barre verticale à gauche
  renderer.fillRect({ startX, topY }, { barWidth, bottomY - topY });

  // B. Dessin du triangle pointant vers la gauche (de la butée jusqu'à endX)
  float triangleStartX = startX + barWidth + 2.0f;     // +2px d'espace
  float totalWidth     = endX - triangleStartX;

  if (totalWidth > 0.0f)
  {
    for (float x = triangleStartX; x <= endX; x += 1.0f)
    {
      float progress = (x - triangleStartX) / totalWidth;
      // Cette fois, plus on avance vers endX (la droite/base), plus le triangle s'élargit
      float currentTopY    = centerY - (centerY - topY) * progress;
      float currentBottomY = centerY + (bottomY - centerY) * progress;

      renderer.drawLine({ x, currentTopY }, { x, currentBottomY });
    }
  }
}
//--------------------------------------------------------------
