#include "ListBox.h"

#include "Button.h"
#include "../graphics/shippingHandler.h"

using namespace std;

ListBox::ListBox ()
{
  colR=0; colG=0; colB=0;
  vertPadding=0; horizPadding=0;
  fontName="NULL_INDEX"; 
  frameBackground="NULL_INDEX"; 
  frameUp="NULL_INDEX"; 
  frameDown="NULL_INDEX"; 
  frameScrollWindow="NULL_INDEX"; 
  frameScrollBar="NULL_INDEX"; 
  frameSelected="NULL_INDEX";
  validElementSelected=false;
  elementIndex=0;
  scrollPosition=0;
}

ListBox::~ListBox ()
{
}

ListBox::ListBox(const ListBox & other)
{
  *this=other;
}

void ListBox::setGraphicHighlightFontColor (uint8_t r, uint8_t g, uint8_t b)
{
  colR=r;
  colG=g;
  colB=b;
}

uint8_t ListBox::getGraphicHighlightFontColorR()
{
  return colR;
}

uint8_t ListBox::getGraphicHighlightFontColorG()
{
  return colG;
}

uint8_t ListBox::getGraphicHighlightFontColorB()
{
  return colB;
}


GraphicTransformation & ListBox::getGraphicTransformation ()
{
  return gt;
}

void ListBox::setGraphicTransformation (GraphicTransformation & a)
{
  gt=a;
}


uint16_t ListBox::getVerticalPadding()
{
  return vertPadding;
}

void ListBox::setVerticalPadding (uint16_t a)
{
  vertPadding=a;
}


uint16_t ListBox::getHorizontalPadding()
{
  return horizPadding;
}

void ListBox::setHorizontalPadding (uint16_t a)
{
  horizPadding=a;
}


const string & ListBox::getFontName ()
{
  return fontName;
}

uint16_t ListBox::getFontSize ()
{
  return fontSize;
}

void ListBox::setFont (const string & a, uint16_t s)
{
  fontName=a;
  fontSize=s;
}


const string & ListBox::getGraphicFrameBackground ()
{
  return frameBackground;
}

void ListBox::setGraphicFrameBackground (const string & a)
{
  frameBackground=a;
}


const string & ListBox::getGraphicFrameUpArrow ()
{
  return frameUp;
}

void ListBox::setGraphicFrameUpArrow (const string & a)
{
 frameUp=a;
}


const string & ListBox::getGraphicFrameDownArrow ()
{
  return frameDown;
}

void ListBox::setGraphicFrameDownArrow (const string & a)
{
  frameDown=a;
}


const string & ListBox::getGraphicFrameScrollWindow ()
{
  return frameScrollWindow;
}

void ListBox::setGraphicFrameScrollWindow (const string & a)
{
  frameScrollWindow=a;
}


const string & ListBox::getGraphicFrameScrollBar ()
{
  return frameScrollWindow;
}

void ListBox::setGraphicFrameScrollBar (const string & a)
{
  frameScrollWindow=a;
}


const string & ListBox::getGraphicFrameSelected ()
{
  return frameSelected;
}

void ListBox::setGraphicFrameSelected (const string & a)
{
  frameSelected=a;
}


void ListBox::setElementHit (uint8_t a)
{
  validElementSelected=true;
  elementIndex=a;
}

void ListBox::clearElementHit ()
{
  validElementSelected=false;
}

int16_t ListBox::getElementHit ()
{
  //returns the element's index.
  //returns -1 if the element hit is invalid.
  if (!validElementSelected)
    return -1;
  return elementIndex;
}


uint8_t ListBox::getScrollPosition()
{
  return scrollPosition;
}

void ListBox::setScrollPosition(uint8_t sp)
{
  scrollPosition=sp;
}

void ListBox::operator=(const ListBox &other)
{
  gt=other.gt;
  colR=other.colR;
  colG=other.colG;
  colB=other.colB;
  vertPadding=other.vertPadding;
  horizPadding=other.horizPadding;
  fontName=other.fontName;
  frameBackground=other.frameBackground;
  frameUp=other.frameUp;
  frameDown=other.frameDown;
  frameScrollWindow=other.frameScrollWindow;
  frameScrollBar=other.frameScrollBar;
  frameSelected=other.frameSelected;
  validElementSelected=other.validElementSelected;
  elementIndex=other.elementIndex;
  scrollPosition=other.scrollPosition;
}

bool ListBox::scrollUp(int numberOfEntries)
{
  //changes the scroll position.
  if (scrollPosition > 0)
    {
      scrollPosition--;
      return true;
    }
  return false;
}

bool ListBox::scrollDown(int numberOfEntries)
{
  //changes the scroll position.
  int maxTextEntriesInListBox=(getHeight()-getVerticalPadding())/(getVerticalPadding()+getFontSize());

  if (scrollPosition < numberOfEntries - maxTextEntriesInListBox)
    {
      scrollPosition++;
      return true;
    }
  return false;
}

  /*
ListBox ::ListBox ()
{
  Button::setDimensions (100, 40, 0);
  elementHit = 0;
  scrollOffset = 0;
  sizeOfElement = 20;
  validElementHit = false;
}

ListBox :: ~ListBox ()
{
}
  
void ListBox ::setDimensions (uint16_t w, uint16_t h, uint8_t size, uint8_t z)
{
  //elements = number of elements visible at once?
  Button::setDimensions (w, h, z);
  sizeOfElement = size;
}

bool ListBox :: checkElement (Input * comm, shippingHandler * sdlRE, string & helpRef)
{
  return false;
  int32_t leftSide = getX () - (sdlRE -> getGFXWidth (getGFXBox ())/2);
  int32_t rightSide = getX () + (sdlRE -> getGFXWidth (getGFXBox ())/2);
  int32_t topSide = getY () - (sdlRE -> getGFXHeight (getGFXBox ())/2);
  int32_t bottomSide = getY () + (sdlRE -> getGFXHeight (getGFXBox ())/2);

  int32_t mouseX = ((threeInts *)(comm -> data)) -> a;
  int32_t mouseY = ((threeInts *)(comm -> data)) -> b;
  int32_t butt = ((threeInts *)(comm -> data)) -> c;

  if (mouseX < leftSide)
    return false;
  if (mouseX > rightSide)
    return false;
  if (mouseY < topSide)
    return false;
  if (mouseY > bottomSide)
    return false;

  //first check if it hit the scroll windows
  if (mouseX > rightSide - (sdlRE -> getGFXWidth (getGFXUpArrow ())) || 
      mouseX > rightSide - (sdlRE -> getGFXWidth (getGFXDownArrow ())))
    {
      //check scroll position
      if (mouseY > topSide + (sdlRE -> getGFXHeight (getGFXUpArrow ())) && 
	  mouseY < bottomSide - (sdlRE -> getGFXHeight (getGFXDownArrow ())))
	{
	  mouseScrollPosition = mouseY - topSide - (sdlRE -> getGFXHeight (getGFXUpArrow ()));
	}
      else if (mouseY < topSide + (sdlRE -> getGFXHeight (getGFXUpArrow ())))
	mouseUpDownScrollCounter --;
      else if (mouseY > bottomSide - (sdlRE -> getGFXHeight (getGFXDownArrow ())))
	mouseUpDownScrollCounter ++;
    }
  else
    //if it didn't hit the scroll window, it hit an element.
    {
      if (butt == MOUSE_BUTTON_ACTION)
	{
	  elementHit = ((mouseY - (getY() - getHeight()/2)) / sizeOfElement + scrollOffset);
	  validElementHit = true;
	}
      if (butt == MOUSE_BUTTON_HELP)
	helpRef = "1"; //STUB
    }
  return true;
}

int16_t ListBox ::getElementHit ()
{
  if (!validElementHit)
    return -1;

  return (int16_t)(elementHit);
}

uint16_t ListBox ::getScrollOffset ()
{
  return scrollOffset;
}

void ListBox ::setFontDetails (const string & f, uint8_t ra, uint8_t ga, uint8_t ba, uint8_t rb, uint8_t gb, uint8_t bb)
{
  Button::setGraphicFont(f);
  Button::setGraphicFontColor(ra, ga, ba);
}

uint8_t ListBox ::getFontDefaultColorR ()
{
  return Button::getGraphicFontColorR ();
}

uint8_t ListBox ::getFontDefaultColorG ()
{
  return Button::getGraphicFontColorG ();
}

uint8_t ListBox ::getFontDefaultColorB ()
{
  return Button::getGraphicFontColorB ();
}

void ListBox ::setFontSelectedColorR (uint8_t a)
{
  colSelr = a;
}
 
void ListBox ::setFontSelectedColorG (uint8_t a)
{
  colSelg = a;
}

void ListBox ::setFontSelectedColorB (uint8_t a)
{
  colSelb = a;
}

uint8_t ListBox ::getFontSelectedColorR ()
{
  return colSelr;
}

uint8_t ListBox ::getFontSelectedColorG ()
{


  return colSelg;
}
 
uint8_t ListBox ::getFontSelectedColorB ()
{
  return colSelb;
}

const string & ListBox ::getGFXBox ()
{
  return gfxBox;
}

void ListBox ::setGFXBox (const string & a)
{
  gfxBox = a;
}

const string & ListBox ::getGFXUpArrow ()
{
  return gfxUpArrow;
}
 
void ListBox ::setGFXUpArrow (const string & a)
{
  gfxUpArrow = a;
}

const string & ListBox ::getGFXDownArrow ()
{
  return gfxDownArrow;
}

void ListBox ::setGFXDownArrow (const string & a)
{
  gfxDownArrow = a;
}

const string & ListBox ::getGFXScrollPosition ()
{
  return gfxScrollPosition;
}

void ListBox ::setGFXScrollPosition (const string & a)
{
  gfxScrollPosition = a;
}

const string & ListBox ::getGFXSelectedItem ()
{
  return gfxSelectedItem;
}

void ListBox ::setGFXSelectedItem (const string & a)
{
  gfxSelectedItem = a;
}

uint8_t ListBox :: getSizeOfElement ()
{
  return sizeOfElement;
}
  */
/*
void ListBox :: draw (shippingHandler * sdlRE, vector <const string *> & vect, vector <bool> & bvect, bool respectCamera)
{
  int32_t leftSide = getX () - (sdlRE -> getGFXWidth (getGFXBox ())/2);
  int32_t rightSide = getX () + (sdlRE -> getGFXWidth (getGFXBox ())/2);
  int32_t topSide = getY () - (sdlRE -> getGFXHeight (getGFXBox ())/2);
  int32_t bottomSide = getY () + (sdlRE -> getGFXHeight (getGFXBox ())/2);
  int32_t scrollDist = (sdlRE -> getGFXHeight (getGFXBox ())) - (sdlRE -> getGFXHeight (getGFXUpArrow ())) - (sdlRE -> getGFXHeight (getGFXDownArrow ())) - (sdlRE -> getGFXHeight (getGFXScrollPosition ()));
  uint8_t onscreenElements = getHeight () / getSizeOfElement ();
  uint8_t numElements = vect.size ();

  if (getElementHit () != -1 && getElementHit () >= scrollOffset && getElementHit () < scrollOffset + onscreenElements && getElementHit () < numElements)
    {
      sdlRE -> drawGFX (getGFXSelectedItem (), getX (), topSide + (sizeOfElement/2) + 
			((getElementHit () - scrollOffset) * sizeOfElement),
			NULL, respectCamera);
    }

  if (numElements > onscreenElements) //draw the scroll bar if it's needed.  
    {
      //adjust the scroll offset
      if (mouseScrollPosition > 0)
	{
	  scrollOffset = (1 + numElements - onscreenElements) * mouseScrollPosition / (sdlRE -> getGFXHeight (getGFXBox ()) - sdlRE -> getGFXHeight (getGFXUpArrow ()) - sdlRE -> getGFXHeight (getGFXDownArrow ()));
	  mouseScrollPosition = 0;
	}
      if (mouseUpDownScrollCounter < 0)
	{
	  if (scrollOffset != 0)
	    scrollOffset --;
	  mouseUpDownScrollCounter ++;
	}
      if (mouseUpDownScrollCounter > 0)
	{scrollOffset ++; mouseUpDownScrollCounter --;}

      //bound scrollOffset
      if (scrollOffset > numElements - onscreenElements)
	scrollOffset = numElements - onscreenElements;

      sdlRE -> drawGFX (getGFXScrollPosition (), rightSide - (sdlRE -> getGFXWidth (getGFXScrollPosition ())/2), 
			getY () - (scrollDist/2) + (scrollDist * scrollOffset / (numElements - onscreenElements)),
			NULL, respectCamera);

  sdlRE -> drawGFX (getGFXUpArrow (), 
		    rightSide - (sdlRE -> getGFXWidth (getGFXUpArrow ())/2),
		    topSide + (sdlRE -> getGFXHeight (getGFXUpArrow ())/2) , 
		    NULL, respectCamera);

  sdlRE -> drawGFX (getGFXDownArrow (), 
		    rightSide - (sdlRE -> getGFXWidth (getGFXDownArrow ())/2),
		    bottomSide - (sdlRE -> getGFXHeight (getGFXDownArrow ())/2), 
		    NULL, respectCamera);
    }

  uint8_t startPos = scrollOffset;
  uint8_t endPos = scrollOffset + onscreenElements;
  uint8_t index = startPos;
  bool done = (startPos == vect.size ());
  
  while (!done)
    {
      if (bvect.at(index))
	sdlRE -> drawText (*vect.at(index), getFont (), leftSide + sizeOfElement, topSide + (index - startPos) * sizeOfElement, getFontSelectedColorR (), getFontSelectedColorG (), getFontSelectedColorB (), respectCamera, 0x5);
      else
	sdlRE -> drawText (*vect.at(index), getFont (), leftSide + sizeOfElement, topSide + (index - startPos) * sizeOfElement, getFontDefaultColorR (), getFontDefaultColorG (), getFontDefaultColorB (), respectCamera, 0x5);
      index ++;
      if (index >= endPos || index >= vect.size ())
	done = true;
    }

  sdlRE -> drawGFX (getGFXBox (), getX (), getY (), NULL, respectCamera);
}
*/
