#include "shippingHandler.h"

void shippingHandler :: drawBitmap (Param & hash, AffineTransformationMatrix & atm)
{
  string keyName = "NULL_INDEX";
  int xPos = 0, yPos = 0;
  bool relativeToCamera=true;

  hash.getString("Resource Name", keyName);
  hash.getInt("X", xPos);
  hash.getInt("Y", yPos);
  hash.getBool("Relative to Camera", relativeToCamera);

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

  map <string, GraphicBitmap> :: iterator iter2;
  iter2 = graphicBitmaps.find (keyName);

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

  SDL_Rect dest, transformOut;

  int destX = xPos, destY = yPos, destW, destH;
  int anchorPointX, anchorPointY, anchorPointX2, anchorPointY2;
  int anchorPointX3, anchorPointY3, anchorPointX4, anchorPointY4;
  float fscaleX=1.0, fscaleY=1.0, fangle=0.0;
  SDL_Surface *tempSurface=NULL;
  FixedInt shiftX, shiftY;
  AffineTransformationMatrix atmInProgress;
  int left, top, right, bottom;
  vector <int> coords;

  calculateDestination (relativeToCamera, destX, destY);

  destW = iter2->second.getPic()->w;
  destH = iter2->second.getPic()->h;

  dest.x = destX;
  dest.y = destY;
  dest.w = destW;
  dest.h = destH;

  //If you don't need to transform the image:
  if (atm.getScaleX() == FixedInt(1) &&
      atm.getScaleY() == FixedInt(1) &&
      atm.getAngle() == FixedInt(0))
    {
      //set the endpoints flag and add endpoints to move the center point off of the center of the image.
      dest.x -= destW/2;
      dest.y -= destH/2;

      SDL_BlitSurface(iter2->second.getPic(), NULL, screenBuffer, &dest);
    }
  else
    {
      //else, use sge's transformation.
      //you need to calculate the new x & y coordinates based on the rotated width & height.

      //Whatever you give as the anchor point, it will rotate and output around that.

      //SDL_Rect sge_transform(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale, Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Uint8 flags)
      //set the endpoints flag and add endpoints to move the center point off of the center of the image.

      //scale 0-256 to 0-360.
      fangle=byteDegreesToDegrees(atm.getAngle().toAngle());
      fscaleX=atm.getScaleX().toFloat();
      fscaleY=atm.getScaleY().toFloat();

      tempSurface = sge_transform_surface(iter2->second.getPic(),
                                          SDL_MapRGBA(iter2->second.getPic()->format, 0,0,0,0),
                                          fangle, fscaleX, fscaleY, 0);

      anchorPointX=0;anchorPointY=0;
      anchorPointX2=destW;anchorPointY2=0;
      anchorPointX3=destW;anchorPointY3=destH;
      anchorPointX4=0;anchorPointY4=destH;

      shiftX=double(destW/2.0);shiftY=double(destH/2.0);
      atmInProgress.shift(shiftX*-1, shiftY*-1);
      atmInProgress.multiplyMatrix(atm);
      shiftX=destX; shiftY=destY;
      atmInProgress.shift(shiftX, shiftY);
      atmInProgress.apply(anchorPointX, anchorPointY);
      atmInProgress.apply(anchorPointX2, anchorPointY2);
      atmInProgress.apply(anchorPointX3, anchorPointY3);
      atmInProgress.apply(anchorPointX4, anchorPointY4);

      //you need to reposition the output square based on the new coordinates.
      //You need to make a bounding box based on the two points.
      coords.clear();
      coords.push_back(anchorPointX);
      coords.push_back(anchorPointX2);
      coords.push_back(anchorPointX3);
      coords.push_back(anchorPointX4);
      left=*min_element(coords.begin(), coords.end());
      right=*max_element(coords.begin(), coords.end());

      coords.clear();
      coords.push_back(anchorPointY);
      coords.push_back(anchorPointY2);
      coords.push_back(anchorPointY3);
      coords.push_back(anchorPointY4);
      top=*min_element(coords.begin(), coords.end());
      bottom=*max_element(coords.begin(), coords.end());

      transformOut.x=left;
      transformOut.y=top;
      transformOut.w=right-left;
      transformOut.h=bottom-top;

      SDL_BlitSurface(tempSurface, NULL, screenBuffer, &transformOut);

      SDL_FreeSurface(tempSurface);
      tempSurface=NULL;
    }
}

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

  return loadResource (keyName, "bitmap");
}

bool shippingHandler :: loadBitmapHelper (const string & index, GraphicBitmap & fram)
{
  //loads the pic if it hasn't been already loaded. Otherwise skip.
  //returns true if it loads a pic.
  SDL_Surface * temp = NULL;

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

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

  xmlChar *keyword;
  keyword = getFirstElementUsingXPath (doc, xpathCtx, "/BitmapManifest/Bitmap[@ID='", index, "']/Filename");

  if (keyword!=NULL)
    filename = (const char *)keyword;
  else
    {
      xmlXPathFreeContext(xpathCtx);
      xmlFreeDoc(doc);
      return false;
    }

  xmlXPathFreeContext(xpathCtx);
  xmlFreeDoc(doc);
  xmlFree(keyword);

  temp = IMG_Load(filename.c_str());

  if (temp == NULL){
    writeToErrorLog ("loadBitmapHelper: Image failed to load.", 2);
    writeToErrorLog (index.c_str(), 2);
    return false;
  }

  //this converts an SDL_Surface to match the screen's stats.
  fram.setPic(SDL_DisplayFormatAlpha (temp));

  SDL_FreeSurface(temp); //Now release it, we're done.
  return true;
}

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

  map <string, GraphicBitmap> :: iterator iter2;
  iter2 = graphicBitmaps.find (keyName);

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

  iter2->second.decRefCount();

  if (iter2->second.getRefCount()==0)
    {
      SDL_FreeSurface(iter2->second.getPic());
      iter2->second.setPic(NULL);
      graphicBitmaps.erase(iter2);
    }
}
