#include "icons.h"
#include "menu.h"

#include <cmath>

namespace
{

constexpr uint8_t COLORS[] = { 0, 0b1, 0b10, 0b100, 0b1000, 0b10000 };

}

using namespace menus;

ManaMenu::ManaMenu(lib::Display& display, lib::Flash& flash) :
  Menu(display, flash),
  current(0),
  previous(0),
  going_right(true),
  progress(0.7f),
  old_progress(progress)
{
}

void ManaMenu::onTick(float dt)
{
  constexpr float PI = 3.1415926f;
  constexpr float STEP = 2 * PI / 6.0f;
  constexpr float RADIUS = 75;
  constexpr float CENTER_X = 120;
  constexpr float CENTER_Y = 190;
  constexpr float MAX_OFFSET = RADIUS / 1.5f;
  constexpr float DT_SCALE_ROTATE = 1.1f;
  constexpr float DT_SCALE_UPDOWN = 1.6f;

  old_progress = progress;

  if (progress < 1.0f)
  {
    progress += dt * DT_SCALE_UPDOWN;
    if (progress > 0.75f)
    {
      progress = 1.0f;
    }

    // erase old
    const float old_offset
      = (1.0f - ease::outElastic(old_progress)) * MAX_OFFSET + RADIUS;
    display->fill(CENTER_X - 15, CENTER_Y - 15 - old_offset, 32, 32, 0, 0, 0);

    // write new
    const float offset
      = (1.0f - ease::outElastic(progress)) * MAX_OFFSET + RADIUS;
    const uint8_t* data = icon::wubrgc(COLORS[previous]);
    display->fill(CENTER_X - 15, CENTER_Y - 15 - offset, 32, 32, data);
  }
  else if (progress < 2.0f)
  {
    progress += dt * DT_SCALE_ROTATE;
    if (progress > 1.75f)
    {
      progress = 2.0f;
    }

    const float old_offset
      = (going_right ? -1 : 1) * STEP * ease::outElastic(old_progress - 1)
        + STEP / 2.0f + (going_right ? 2 * STEP : 0);
    const float offset
      = (going_right ? -1 : 1) * STEP * ease::outElastic(progress - 1)
        + STEP / 2.0f + (going_right ? 2 * STEP : 0);

    // erase previous
    for (int i = 0; i < sizeof(COLORS) / sizeof(*COLORS); i++)
    {
      const float angle = i * STEP - old_offset;

      const float x = cosf(angle) * RADIUS;
      const float y = sinf(angle) * RADIUS;

      const int left = x - 15 + CENTER_X;
      const int top = y - 15 + CENTER_Y;

      display->fill(left, top, 32, 32, 0, 0, 0);
    }

    // write new
    for (int i = 0; i < sizeof(COLORS) / sizeof(*COLORS); i++)
    {
      const float angle = (i - current) * STEP - offset;

      const float x = cosf(angle) * RADIUS;
      const float y = sinf(angle) * RADIUS;

      const int left = x - 15 + CENTER_X;
      const int top = y - 15 + CENTER_Y;

      const uint8_t* data = icon::wubrgc(COLORS[i]);
      display->fill(left, top, 32, 32, data);
    }
  }
  else if (progress < 3.0f)
  {
    progress += dt * DT_SCALE_UPDOWN;
    if (progress > 2.75f)
    {
      progress = 3.0f;
    }

    const float old_offset
      = ease::outElastic(old_progress - 2.0f) * MAX_OFFSET + RADIUS;
    const float offset
      = ease::outElastic(progress - 2.0f) * MAX_OFFSET + RADIUS;

    display->fill(CENTER_X - 15, CENTER_Y - 15 - old_offset, 32, 32, 0, 0, 0);

    // write new
    {
      const uint8_t* data = icon::wubrgc(COLORS[current]);
      display->fill(CENTER_X - 15, CENTER_Y - 15 - offset, 32, 32, data);
    }
  }
}
void ManaMenu::onResume()
{
  display->clear();
  progress = 0.7f;
  going_right = true;
}

void ManaMenu::onLeftPressed()
{
  if (progress < 3.0f)
  {
    return;
  }

  going_right = false;

  previous = current;
  if (current == 5)
  {
    current = 0;
  }
  else
  {
    current += 1;
  }

  progress = 0.0f;
}
void ManaMenu::onLeftHeld() {}

void ManaMenu::onMenuPressed()
{
  push_menu<CMCMenu>(*display, *flash, COLORS[current]);
}
void ManaMenu::onMenuHeld() {}

void ManaMenu::onRightPressed()
{
  if (progress < 3.0f)
  {
    return;
  }

  going_right = true;

  previous = current;
  if (current == 0)
  {
    current = 5;
  }
  else
  {
    current -= 1;
  }

  progress = 0.0f;
}
void ManaMenu::onRightHeld() {}
