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


#define MOVE_FONT_BASELINE 25
#define MOVE_FONT_HEIGHT 42

#define MOVE_REFRESHRATE 1000

#define MOVE_LINE_MARGIN 7
#define MOVE_LINE_HEIGHT (MOVE_FONT_BASELINE + (2 * MOVE_LINE_MARGIN))

#define MOVE_STOP_SMALL_TEXT_SIZE
#define MOVE_STOP_SMALL_LINE_HEIGHT 8

#define MOVE_ARROW_WIDTH 20
#define MOVE_ARROW_HEIGHT 10
#define MOVE_ARROW_YOFFSET ((MOVE_LINE_HEIGHT - MOVE_ARROW_HEIGHT) / 2)


void MoveScreen::onShow()
{
  auto display = this->getDisplay();
  //auto startY = (Config::DisplayHeight - (MOVE_LINE_HEIGHT * 3)) / 2;
  auto startY = MOVE_LINE_HEIGHT;
  auto arrowY = startY + MOVE_LINE_HEIGHT + MOVE_ARROW_YOFFSET;
  auto arrowX = (Config::DisplayWidth - MOVE_ARROW_WIDTH) / 2;
  auto stopY = Config::DisplayHeight - MOVE_LINE_HEIGHT;

  display->fillScreen(Config::ColorMoveBackground);

  // Stop
  display->setFont(nullptr);
  display->setTextColor(Config::ColorMoveStop);
  this->printCentered("Press any button to", stopY - MOVE_STOP_SMALL_LINE_HEIGHT);

  display->setFont(&FreeSansBold18pt7bTrimmed);
  this->printCentered("STOP", stopY + MOVE_FONT_BASELINE + MOVE_LINE_MARGIN);

  char targetHeightText[6];
  getDisplayHeight(&targetHeightText[0], State.MoveTarget);
  display->setTextColor(Config::ColorMoveCurrent);

  // Target and arrow
  if (State.MoveDirection == Direction::Up)
  {
    this->currentHeightY = startY + (MOVE_LINE_HEIGHT * 2);

    this->printCentered(&targetHeightText[0], startY + MOVE_FONT_BASELINE + MOVE_LINE_MARGIN);

    display->fillTriangle(
      arrowX + (MOVE_ARROW_WIDTH / 2), arrowY,                // Top middle
      arrowX, arrowY + MOVE_ARROW_HEIGHT,                     // Bottom left
      arrowX + MOVE_ARROW_WIDTH, arrowY + MOVE_ARROW_HEIGHT,  // Bottom right
      Config::ColorMoveArrow);
  }
  else
  {
    this->currentHeightY = startY;

    this->printCentered(&targetHeightText[0], startY + (MOVE_LINE_HEIGHT * 2) + MOVE_FONT_BASELINE + MOVE_LINE_MARGIN);

    display->fillTriangle(
      arrowX, arrowY,                                                 // Top left
      arrowX + MOVE_ARROW_WIDTH, arrowY,                              // Top right
      arrowX + (MOVE_ARROW_WIDTH / 2), arrowY + MOVE_ARROW_HEIGHT,    // Bottom middle
      Config::ColorMoveArrow);
  }

  this->lastRefresh = State.CurrentTime;
  this->drawCurrentHeight();
}


void MoveScreen::onButton(Button button)
{
  motorStateStop();
  this->getScreenManager()->show<HomeScreen>();
}


void MoveScreen::onTick()
{
  if (State.MoveDirection == Direction::None)
  {
    this->getScreenManager()->show<HomeScreen>();
    return;
  }

  // Don't update every tick, monitoring the current height is more
  // important and the flicker would be unpleasant as well.
  if (State.CurrentTime - this->lastRefresh >= MOVE_REFRESHRATE)
  {
    this->drawCurrentHeight();
    this->lastRefresh = State.CurrentTime;
  }
}


void MoveScreen::drawCurrentHeight()
{
  auto display = this->getDisplay();

  char currentHeightText[6];
  getDisplayHeight(&currentHeightText[0], State.CurrentHeight);

  if (this->lastTextWidth > 0)
    display->fillRect((Config::DisplayWidth - this->lastTextWidth) / 2, this->currentHeightY, this->lastTextWidth, MOVE_LINE_HEIGHT, Config::ColorMoveBackground);

  display->setTextColor(Config::ColorMoveTarget);
  this->lastTextWidth = this->printCentered(&currentHeightText[0], this->currentHeightY + MOVE_FONT_BASELINE);
}