
#include "libOLED/displayclass.H"

void display_t::printString(font_t &font, char const *string, uint16_t length,
                            colour_t colour)
{
  setPixelMode(colour);
  uint16_t const xSpacing = font.width() + 1;
  for (uint16_t yt = 0; yt < font.height(); yt++) // iterate down scan lines
  {
    uint16_t ys = m_cursor_y + yt;
    for (uint16_t xt = 0; xt < length; xt++)
    {
      unsigned char c = string[xt];
      uint16_t xs = xt * xSpacing + m_cursor_x;
      for (uint16_t j = 0; j < font.spacing(); j++)
      {
        drawPixel(j + xs, ys, font.getPixel(c, j, yt));
      }
    }
  }
  // move the cursor.
  m_cursor_x += xSpacing * length;
}

// scale is multiplied by 256
void display_t::printScaledString(font_t &font, char const *string,
                                  uint16_t length, uint16_t scale,
                                  colour_t colour)
{
  uint16_t xt, yt, jt, curr_x = 0;
  uint16_t curr_y = m_cursor_y;
  if (scale < 1)
    return;
  setPixelMode(colour);

  for (yt = 0; yt < font.height() * 256; yt += scale) // iterate down scan lines
  {
    // iterate along the string
    // local x plotting coordinate
    curr_x = m_cursor_x;
    for (xt = 0; xt < length; xt++)
    {
      for (jt = 0; jt < (font.spacing()) * 256; jt += scale)
      {
        unsigned char c = (string[xt]);
        drawPixel(curr_x, curr_y, font.getPixel(c, jt / 256, yt / 256));
        curr_x++;
      }
    }
    curr_y++;
  }
  if (curr_x > width())
  {
    curr_x = 0;
  }
  m_cursor_x = curr_x;
}

uint8_t
display_t::formatNum(char *buff, uint8_t siz, uint8_t digits, uint8_t dp_pos, int val)
{
  if (dp_pos != NO_DECIMAL)
    digits++;
  uint8_t pos = digits;
  uint8_t dp_loc = pos - dp_pos;
  uint8_t sign = 0;
  if (val < 0)
  {
    sign = 1;
    val = -val;
  }

  buff[pos] = 0;
  while (pos && pos < siz)
  {
    if (pos == dp_loc)
    {
      buff[--pos] = '.';
    }
    else
    {
      buff[--pos] = val % 10 + '0';
      val /= 10;
      if (val == 0 && pos < dp_loc)
        break;
    }
  }
  if (sign)
  {
    buff[--pos] = '-';
  }
  return digits;
}

void display_t::fontDigits(font_t &font, uint8_t digits, uint8_t dp_pos, int val, colour_t colour)
{
  char buff[10] = "        ";
  uint8_t wid = formatNum(buff, sizeof(buff), digits, dp_pos, val);
  printString(font, buff, wid, colour);
}

int8_t display_t::fontSigDigits(font_t &font, uint8_t x, uint8_t y, bool right_justify, uint8_t dp_pos,
                                 int val, colour_t colour)
{
  char digits;
  uint8_t width;
  char sign = 0;
  int uval;
  if (val < 0)
  {
    uval = -val;
    sign = 1; // mark as negative
  }
  else
  {
    uval = val;
  }
  if (uval < 10) // always one digit for a sign or space, one for a digit
  {
    digits = 1;
  }
  if (uval >= 10 && uval < 100)
  {
    digits = 2;
  }
  if (uval >= 100 && uval < 1000)
  {
    digits = 3;
  }
  if (uval >= 1000)
  {
    digits = 4;
  }
  // backup for the - sign if right justified
  if (right_justify)
  {
    if (dp_pos != NO_DECIMAL)
    {
      digits += 2;
    }
    else
    {
      digits += 1;
    }
    width = digits;
    x -= digits * font.spacing();
  }
  else
  {
    width = digits;
    if (dp_pos != NO_DECIMAL)
      ++width;
    if (sign)
      ++width;
  }

  gotoxy(x, y);
  fontDigits(font, digits, dp_pos, val, colour);
  // right justify always leaves space for sign
  return width;
}
