#include "counter.h"
#include <stdint.h>
#include <ssd1306xled.h>
#include "state.h"
#include "../buttons.h"


#define CounterMinValue -99
#define CounterMaxValue 999

int16_t lastDrawnCounter = 9999;
int16_t counter = 0;


// Forward declarations
void drawCounter();
void drawDigit(uint8_t* column, uint8_t digit);
void drawMinusSign(uint8_t* column);
void blankDigitColumn(uint8_t* column, uint8_t width);


void handleCounterScreen()
{
  if (button_is_pressed_or_repeated(&buttonUp))
  {
    if (counter < CounterMaxValue)
      counter++;
  }
  else if (button_is_pressed_or_repeated(&buttonDown))
  {
    if (counter > CounterMinValue)
      counter--;
  }

  if (counter != lastDrawnCounter || getScreenInvalidated())
  {
    drawCounter();
    lastDrawnCounter = counter;
  }
}


void drawCounter()
{
  uint8_t column = DigitFullOffset;

  if (counter < -9)
  {
    // Two digit negative, blank left and right (minimizes flicker) and spacing
    blankDigitColumn(&column, SpacingNegativeLeft2);
    drawMinusSign(&column);
    blankDigitColumn(&column, DigitSpacing);

    drawDigit(&column, (-counter) / 10);
    blankDigitColumn(&column, DigitSpacing);
    drawDigit(&column, (-counter) % 10);

    blankDigitColumn(&column, SpacingNegativeRight2);
  }
  else if (counter < 0)
  {
    // Single digit negative, similar
    blankDigitColumn(&column, SpacingNegativeLeft1);
    drawMinusSign(&column);
    blankDigitColumn(&column, DigitSpacing);
    drawDigit(&column, -counter);
    blankDigitColumn(&column, SpacingNegativeRight1);
  }
  else if (counter < 10)
  {
    // Single digit, blank left and right only
    blankDigitColumn(&column, SpacingLeft1);
    drawDigit(&column, counter);
    blankDigitColumn(&column, SpacingRight1);
  }
  else if (counter < 100)
  {
    // Two digits, you know the drill by now
    blankDigitColumn(&column, SpacingLeft2);

    drawDigit(&column, counter / 10);
    blankDigitColumn(&column, DigitSpacing);
    drawDigit(&column, counter % 10);

    blankDigitColumn(&column, SpacingRight2);
  }
  else
  {
    // Three digits
    drawDigit(&column, counter / 100);
    blankDigitColumn(&column, DigitSpacing);
    drawDigit(&column, (counter % 100) / 10);
    blankDigitColumn(&column, DigitSpacing);
    drawDigit(&column, counter % 10);
  }
}


void drawDigit(uint8_t* column, uint8_t digit)
{
  if (digit > 9) return;

  uint8_t yEnd = DigitPage + DigitRows;
  uint16_t bitmapOffset = digit * DigitBytesPerChar;

  for (uint8_t y = DigitPage; y < yEnd; y++)
  {
    ssd1306_setpos(*column, y);
    ssd1306_send_data_start();

    for (uint8_t x = 0; x < DigitWidth; x++)
    {
      ssd1306_send_byte(pgm_read_byte(&Digits[bitmapOffset]));
      bitmapOffset++;
    }

    ssd1306_send_data_stop();
  }

  (*column) += DigitWidth;
}


void drawMinusSign(uint8_t* column)
{
  uint8_t yEnd = DigitPage + DigitRows;
  uint16_t bitmapOffset = 0;

  for (uint8_t y = DigitPage; y < yEnd; y++)
  {
    ssd1306_setpos(*column, y);
    ssd1306_send_data_start();

    for (uint8_t x = 0; x < MinusSignWidth; x++)
    {
      ssd1306_send_byte(pgm_read_byte(&MinusSign[bitmapOffset]));
      bitmapOffset++;
    }

    ssd1306_send_data_stop();
  }

  (*column) += MinusSignWidth;
}


void blankDigitColumn(uint8_t* column, uint8_t width)
{
  uint8_t yEnd = DigitPage + DigitRows;
  for (uint8_t y = DigitPage; y < yEnd; y++)
  {
    ssd1306_setpos(*column, y);
    ssd1306_send_data_start();

    for (uint8_t i = 0; i < width; i++)
      ssd1306_send_byte(0);

    ssd1306_send_data_stop();
  }

  (*column) += width;
}