#include "./home.h"
#include "./move.h"
#include "fonts/FreeSansBold18pt7b.trimmed.h"
#include "include/config.h"
#include "lib/settings.h"
#include "lib/motorstate.h"
#include "./menu.h"


#define HOME_FONT_BASELINE 25
#define HOME_FONT_HEIGHT 42

#define PRESET_MARGIN 7

// HOME_FONT_BASELINE is not a mistake, as there are no characters used which
// go below the baseline.
#define PRESET_LINEHEIGHT (HOME_FONT_BASELINE + (2 * PRESET_MARGIN))

#define HOME_ARROW_WIDTH 10
#define HOME_ARROW_HEIGHT 20
#define HOME_ARROW_MARGIN 8
#define HOME_ARROW_YOFFSET ((PRESET_LINEHEIGHT - HOME_ARROW_HEIGHT) / 2)

#define HOME_INDICATOR_OFFSET (HOME_ARROW_WIDTH + (2 * HOME_ARROW_MARGIN))

#define HOME_MENU_Y 100



void HomeScreen::onShow()
{
  this->showTime = State.CurrentTime;

  auto display = this->getDisplay();

  display->setFont(&FreeSansBold18pt7bTrimmed);
  display->fillScreen(Config::ColorHomeBackground);

  this->drawPreset1();
  this->drawMenu();
  this->drawPreset2();

  this->drawNonPresetHeight();
}


void HomeScreen::onButton(Button button)
{
  if (this->idle)
  {
    this->getScreenManager()->displayOn();
    this->idle = false;
    this->showTime = State.CurrentTime;

    // TODO: should preset buttons activate immediately?
    return;
  }

  switch (button)
  {
    case Button::Up:
      motorStateMoveTo(Settings.Height.Preset[0]);
      this->getScreenManager()->show<MoveScreen>();
      break;

    case Button::Down:
      motorStateMoveTo(Settings.Height.Preset[1]);
      this->getScreenManager()->show<MoveScreen>();
      break;

    case Button::Menu:
      this->getScreenManager()->show<MenuScreen>();
      break;
  }
}


void HomeScreen::onTick()
{
  if (!this->idle && State.CurrentTime - this->showTime >= Config::DisplayIdleTime)
  {
    this->getScreenManager()->displayOff();
    this->idle = true;
  }
}


void HomeScreen::drawPreset1()
{
  //this->drawPreset(0, Settings.Height.Preset[0]);
  this->drawPreset(0, State.CurrentHeight);
}


void HomeScreen::drawPreset2()
{
  this->drawPreset(Config::DisplayHeight - PRESET_LINEHEIGHT, Settings.Height.Preset[1]);
}


void HomeScreen::drawNonPresetHeight()
{
  auto display = this->getDisplay();
  auto y = PRESET_LINEHEIGHT;

  if (State.CurrentHeight != Settings.Height.Preset[0] &&
      State.CurrentHeight != Settings.Height.Preset[1])
  {
    display->setTextColor(Config::ColorNonPresetText);
    this->drawHeight(y, State.CurrentHeight);
  }
}


void HomeScreen::drawArrow(int16_t y, uint16_t color)
{
  this->getDisplay()->fillTriangle(
    HOME_ARROW_MARGIN + HOME_ARROW_WIDTH, y + HOME_ARROW_YOFFSET,                       // Top right
    HOME_ARROW_MARGIN, y + HOME_ARROW_YOFFSET + (HOME_ARROW_HEIGHT / 2),                // Middle left
    HOME_ARROW_MARGIN + HOME_ARROW_WIDTH, y + HOME_ARROW_YOFFSET + HOME_ARROW_HEIGHT,   // Bottom right
    color);
}


void HomeScreen::drawPreset(int16_t y, uint16_t value)
{
  auto display = this->getDisplay();
  uint16_t textColor;
  uint16_t backgroundColor;
  uint16_t arrowColor;

  // An exact comparison is enough here, the movement code takes care of that if it's "close enough"
  if (value == State.CurrentHeight)
  {
    textColor = Config::ColorPresetSelectedText;
    backgroundColor = Config::ColorPresetSelectedBackground;
    arrowColor = 0;
  }
  else
  {
    textColor = Config::ColorPresetText;
    backgroundColor = Config::ColorPresetBackground;
    arrowColor = Config::ColorPresetArrow;
  }

  display->fillRect(0, y, Config::DisplayWidth, PRESET_LINEHEIGHT, backgroundColor);

  if (arrowColor)
    this->drawArrow(y, arrowColor);

  display->setTextColor(textColor);
  this->drawHeight(y, value);
}


void HomeScreen::drawHeight(int16_t y, uint16_t value)
{
  auto display = this->getDisplay();

  char textValue[6];
  getDisplayHeight(&textValue[0], value);

  this->printCentered(&textValue[0], y + HOME_FONT_BASELINE + PRESET_MARGIN);
}


void HomeScreen::drawMenu()
{
  auto display = this->getDisplay();

  this->drawArrow(HOME_MENU_Y, Config::ColorHomeMenuArrow);

  display->setTextColor(Config::ColorHomeMenuText);
  this->printCentered("Menu", HOME_MENU_Y + HOME_FONT_BASELINE + PRESET_MARGIN);
}
