#include "shippingHandler.h"

//extracts needed variables for below
void shippingHandler :: drawFont (Param & hash)
{
  string str = "STUB STRING", keyName = "NULL_INDEX";
  int xPos = 0, yPos = 0, colorRed = 128, colorGreen = 128, colorBlue = 128, orientation = DRAW_ANCHOR_CENTER;
  bool respectCamera = true;

  hash.getString("String", str);
  hash.getString("Resource Name", keyName);
  hash.getInt("X", xPos);
  hash.getInt("Y", yPos);
  hash.getInt("Red", colorRed);
  hash.getInt("Green", colorGreen);
  hash.getInt("Blue", colorBlue);
  hash.getInt("Orientation", orientation);
  hash.getBool("Relative to Camera", respectCamera);

  drawFont (str, keyName, xPos, yPos, colorRed, colorGreen, colorBlue, respectCamera, orientation);
}

void shippingHandler :: drawFont (const string & str, const string & keyName, int32_t xPos, int32_t yPos, uint8_t colorRed, uint8_t colorGreen, uint8_t colorBlue, bool respectCamera, uint8_t orientation)
{
  //draws a source at the given coordinates.

  //respectCamera : If false, xPos and yPos are screen coordinates and ignore camera scroll.

  //orientation uses bit masks.
  //Horizontal
  //0x1 : Put text to the right of the coordinate.
  //0x2 : Put text to the left of the coordinate.
  //Otherwise, horizontally center the text.
  //Vertical
  //0x4 : Put text Below the coordinate.
  //0x8 : Put text Above the coordinate.
  //Otherwise, vertically center the text.

  if (keyName.empty() || keyName == "NULL_INDEX")
    return;

  if (str.empty())
    return;

  map <string, GraphicFont> :: iterator iter2;
  iter2 = fonts.find (keyName);

  if (iter2 == fonts.end())
    return;

  SDL_Color textCol;
  textCol.r = colorRed;
  textCol.g = colorGreen;
  textCol.b = colorBlue;

  SDL_Rect tPos;

  int destX = xPos, destY = yPos, destW, destH;

  if (respectCamera)
    {
      destX = (screenResolutionX/2 + xPos - observerX);
      destY = (screenResolutionY/2 + yPos - observerY);
    }
  else
    {
      destX = xPos;
      destY = yPos;
    }

  SDL_Surface * textOutput;
  textOutput = TTF_RenderText_Solid (iter2->second.getFont(), str.c_str (), textCol);

  destW = textOutput -> w;
  destH = textOutput -> h;

  if (orientation & 0x1)
    destX += destW/2;
  else if (orientation & 0x2)
    destX -= destW/2;
  else
    destX += 0;

  if (orientation & 0x4)
    destY += destH/2;
  else if (orientation & 0x8)
    destY -= destH/2;
  else
    destY += 0;

  tPos.x = destX - destW/2;
  tPos.y = destY - destH/2;
  tPos.w = destW;
  tPos.h = destH;

  SDL_BlitSurface(textOutput, NULL, screenBuffer, &tPos);
  SDL_FreeSurface (textOutput);
}


uint16_t shippingHandler :: getFontSize (const string & keyName)
{
  if (keyName.empty() || keyName == "NULL_INDEX")
    return 0;

  map <string, GraphicFont> :: iterator iter2;
  iter2 = fonts.find (keyName);

  if (iter2 == fonts.end())
    return 0;

  return (*iter2).second.getFontSize ();
}

uint16_t shippingHandler :: getFontSpacing (const string & keyName)
{
  if (keyName.empty() || keyName == "NULL_INDEX")
    return 0;

  map <string, GraphicFont> :: iterator iter2;
  iter2 = fonts.find (keyName);

  if (iter2 == fonts.end())
    return 16;

  return (*iter2).second.getSpacing ();
}


bool shippingHandler :: loadFont (string & keyName)
{
  //simply a front to loadResource.
  if (keyName.empty() || keyName == "NULL_INDEX")
    {
      keyName="NULL_INDEX";
      return false;
    }

  return loadResource (keyName, "font");
}

bool shippingHandler :: loadFontHelper (const string & keyName, GraphicFont & newFont)
{
  //attempts to read the file and load the object.

  //parse the xml file and find the filename for the given index
  xmlDocPtr doc;
  xmlXPathContextPtr xpathCtx;

  if (!prepareXMLFile (doc, xpathCtx, "resources/FontManifest.xml", ""))
    {
      return false;
    }

  xmlChar *keyword;
  keyword = getFirstElementUsingXPath (doc, xpathCtx, "/FontManifest/Font[@ID='", keyName, "']/Filename");

  if (keyword==NULL)
    {
      xmlXPathFreeContext(xpathCtx);
      xmlFreeDoc(doc);
      return false;
    }

  string fileName;
  fileName = (const char *)keyword;
  xmlFree(keyword);
  keyword = getFirstElementUsingXPath (doc, xpathCtx, "/FontManifest/Font[@ID='", keyName, "']/Size");

  int fontSize;

  if (keyword!=NULL)
    {
      fontSize=int(xmlXPathCastStringToNumber(keyword));
      newFont.setFontSize(fontSize);
      xmlFree(keyword);
    }
  else
    {
      newFont.setFontSize(14);
    }

  SDL_ClearError ();
  newFont.setFont(TTF_OpenFont (fileName.c_str(), newFont.getFontSize()));

  keyword = getFirstElementUsingXPath (doc, xpathCtx, "/FontManifest/Font[@ID='", keyName, "']/Spacing");
  int spacing;
  if (keyword!=NULL)
    {
      spacing=int(xmlXPathCastStringToNumber(keyword));
      newFont.setSpacing(spacing);
      xmlFree(keyword);
    }
  else
    {
      newFont.setSpacing(16);
    }

  if (newFont.getFont() == NULL)
    {
      writeToErrorLog ("loadFont: font not loaded for index", 1);
      writeToErrorLog (keyName.c_str(), 1);
      writeToErrorLog (TTF_GetError(), 2);

      xmlXPathFreeContext(xpathCtx);
      xmlFreeDoc(doc);
      return false;
    }

  xmlXPathFreeContext(xpathCtx);
  xmlFreeDoc(doc);
  return true;
}


void shippingHandler :: releaseFont (const string & keyName)
{
  if (keyName.empty() || keyName == "NULL_INDEX")
    return;

  map <string, GraphicFont> :: iterator iter2;
  iter2 = fonts.find (keyName);

  if (iter2 == fonts.end())
    return;

  iter2->second.decRefCount();

  if (iter2->second.getRefCount()==0)
    {
      TTF_CloseFont(iter2->second.getFont());
      iter2->second.setFont(NULL);
      fonts.erase(iter2);
    }
}

//tries to draw a line of text to determine its size. TTF Fonts are not fixed width so this will give a good estimate of the size.
//The height might be too much, as TTF rendering leaves a lot of blank space below the letters.
void shippingHandler::getTextDimensions (const string & input, const string & fontName, uint16_t & width, uint16_t & height)
{
  if (fontName.empty() || fontName == "NULL_INDEX")
    return;

  //if text is blank, you know what to do.
  if (input.empty())
    {
      width=0;
      height=0;
      return;
    }

  map <string, GraphicFont> :: iterator iter2;
  iter2 = fonts.find (fontName);

  if (iter2 == fonts.end())
    return;

  SDL_Color textCol;
  textCol.r = 128;
  textCol.g = 128;
  textCol.b = 128;

  SDL_Surface * textOutput;
  textOutput = TTF_RenderText_Solid ((*iter2).second.getFont(), input.c_str (), textCol);

  width = textOutput -> w;
  height = textOutput -> h;

  SDL_FreeSurface (textOutput);
  return;
}
