#include "TextContainer.h"

TextContainer::TextContainer()
{
  clear();
}

TextContainer::~TextContainer()
{
  clear();
}

//clears everything. Use this if you want to use the TextContainer for something else entirely.
void TextContainer::clear()
{
  fmt.clear();
  posX=0; posY=0;
  width=100; height=100;
  marginTop=0; marginLeft=0; marginBottom=0; marginRight=0;
  numberOfLinesPerPage=1;
  lineSpacing=16;
  colorR.clear();
  colorG.clear();
  colorB.clear();
  lineCursor=0;
}


//position
void TextContainer::setPositionX (int p)
{
  posX=p;
}

int TextContainer::getPositionX ()
{
  return posX;
}

void TextContainer::setPositionY (int p)
{
  posY=p;
}

int TextContainer::getPositionY ()
{
  return posY;
}


//size of the TextContainer itself.
void TextContainer::setTextContainerWidth(int p)
{
  if (p > 0)
    width=p;
}

int TextContainer::getTextContainerWidth()
{
  return width;
}

void TextContainer::setTextContainerHeight(int p)
{
  if (p > 0)
    height=p;
}

int TextContainer::getTextContainerHeight()
{
  return height;
}


  //margins for the text
void TextContainer::setMarginTop (int p)
{
  marginTop=p;
}

int TextContainer::getMarginTop ()
{
  return marginTop;
}

void TextContainer::setMarginLeft (int p)
{
  marginLeft=p;
}

int TextContainer::getMarginLeft ()
{
  return marginLeft;
}

void TextContainer::setMarginBottom (int p)
{
  marginBottom=p;
}

int TextContainer::getMarginBottom ()
{
  return marginBottom;
}

void TextContainer::setMarginRight (int p)
{
  marginRight=p;
}

int TextContainer::getMarginRight ()
{
  return marginRight;
}


  //line spacing: How much space to put inbetween each line
void TextContainer::setLineSpacing(int p)
{
  if (p > 0)
    lineSpacing=p;
}

int TextContainer::getLineSpacing()
{
  return lineSpacing;
}


//adding text is handled in shippingHandler, as it relies on graphical dimensions.

//scrolling text: takes a bool argument to destroy the text. Set it to true to destroy the text you scroll offscreen.
bool TextContainer::scrollDown(int numLines, bool destroyText)
{
  if (fmt.size()==0)
    {
      lineCursor=0;
      return false;
    }

  if (!destroyText)
    {
      //Move the mouse cursor down as low as you can.
      lineCursor += numLines;
    }
  else
    {
      //Delete the line at cursor as long as it isn't the end.
      for (int i = 0; i < numLines && !fmt.empty(); i++)
        {
          if (lineCursor<int(fmt.size()))
            fmt.erase(fmt.begin()+lineCursor);
        }
    }

  if (lineCursor >= int(fmt.size()))
    lineCursor=fmt.size()-1;
  return true;
}

bool TextContainer::scrollUp(int numLines, bool destroyText)
{
  if (lineCursor<=0)
    return false;

  if (!destroyText)
    {
      //Move the mouse cursor up high as you can.
      lineCursor -= numLines;
    }
  else
    {
      //Delete the line at cursor + page if it exists.

      //pop the first numLines lines.
      for (int i = 0; i < numLines && !fmt.empty(); i++)
        {
          if (lineCursor+numberOfLinesPerPage-1<int(fmt.size()) && lineCursor > 0)
            fmt.erase(fmt.begin()+lineCursor+numberOfLinesPerPage-1);
          lineCursor--;
        }
    }

  if (lineCursor < 0)
    lineCursor=0;
  return true;
}

bool TextContainer::scrollDownPage(bool destroyText)
{
  return scrollDown (numberOfLinesPerPage, destroyText);
}

bool TextContainer::scrollUpPage(bool destroyText)
{
  return scrollUp (numberOfLinesPerPage, destroyText);
}

void TextContainer::destroyAllText()
{
  fmt.clear();
  lineCursor=0;
}


//returns the contents of the formatted text. Necessary for external functions to add text.
vector<vector<FormattedText> > & TextContainer::getFormattedText()
{
  return fmt;
}

//add colors.
int TextContainer::addFontColor (int r, int g, int b)
{
  colorR.push_back((uint8_t)(r%256));
  colorG.push_back((uint8_t)(g%256));
  colorB.push_back((uint8_t)(b%256));
  return (colorR.size()-1);
}

uint8_t TextContainer::getFontColorR (int i)
{
  if (i < 0 || i >= int(colorR.size()))
    return 255;
  return colorR[i];
}

uint8_t TextContainer::getFontColorG (int i)
{
  if (i < 0 || i >= int(colorG.size()))
    return 255;
  return colorG[i];
}

uint8_t TextContainer::getFontColorB (int i)
{
  if (i < 0 || i >= int(colorB.size()))
    return 255;
  return colorB[i];
}

bool TextContainer::getFontColors (int i, uint8_t & r, uint8_t & g, uint8_t & b)
{
  if (i < 0 || i >= int(colorR.size()) || i >= int(colorG.size()) || i >= int(colorB.size()))
    return false;
  r=colorR[i];
  g=colorG[i];
  b=colorB[i];
  return true;
}

//number of lines
int TextContainer::getNumberOfLinesPerPage ()
{
  return numberOfLinesPerPage;
}

void TextContainer::setNumberOfLinesPerPage (int p)
{
  if (p >= 0)
    numberOfLinesPerPage = p;
}

//Returns references to the visible text, aka the stuff between lineCursor and lineCursor+numberOfLinesPerPage.
//verticalOffset is the height of the first visible line, so everything is relative to it.
void TextContainer::getVisibleText (int & verticalOffset, vector <vector<FormattedText> > :: iterator & startPoint,
                                    vector <vector<FormattedText> > :: iterator & endPoint)
{
  startPoint=fmt.begin()+lineCursor;
  endPoint=startPoint;

  if (fmt.empty())
    {
      verticalOffset=0;
      return;
    }

  verticalOffset=startPoint->begin()->getY();

  int counter=0;
  bool done = false;

  while (!done)
    {
      if (endPoint==fmt.end()||counter==numberOfLinesPerPage)
        done=true;
      else
        {
          counter++;
          endPoint++;
        }
    }
}

//Fonts
const string & TextContainer::getFontName()
{
  return fontName;
}

void TextContainer::setFontName (const string & fnt)
{
  fontName=fnt;
}
