/* **********************************************************************************************************************
   Included Header Files
   **********************************************************************************************************************/

#include "VDSprite.h"



/* **********************************************************************************************************************
   Constructors
   ------------
   #param  direct3DDevice  Pointer to the display adapter device.
   #param  textureFile     Name of the texture (with directory structure included).
   #param  width           Width of the texture.
   #param  height          Height of the texture.
   #param  aPosition       Position of the sprite on the screen.
   #param  isStaticSprite  Is the sprite static?
   #param  isNPCSprite     Is the sprite an NPC?
   **********************************************************************************************************************/

VDSprite::VDSprite() {
    texture = NULL;
    SecureZeroMemory(&sourceRectangle, sizeof(sourceRectangle));
    SecureZeroMemory(&center, sizeof(center));
    SecureZeroMemory(&position, sizeof(position));
    color = NULL;
    isStatic = FALSE;
    isNPC = FALSE;
    isDead = FALSE;
    direction = 0;
    isMoving = FALSE;
    movingDuration = 0;
};

VDSprite::VDSprite(LPDIRECT3DDEVICE9 direct3DDevice, LPCSTR textureFile, RECT sourceRect, D3DXVECTOR3 aPosition, D3DCOLOR colorKey, int isStaticSprite, int isNPCSprite) {
    HRESULT returnValue = NULL;

    returnValue = D3DXCreateTextureFromFileEx(direct3DDevice, textureFile, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, colorKey, NULL, NULL, &texture);
    if (returnValue != D3D_OK) {
        VDDirectXError(textureFile, returnValue, __FILE__, __LINE__);
    };
    (void) SetRect(&sourceRectangle, sourceRect.left, sourceRect.top, sourceRect.right, sourceRect.bottom);
    center = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    position = aPosition;
    color = D3DCOLOR_ARGB(255, 255, 255, 255);
    isStatic = isStaticSprite;
    isNPC = isNPCSprite;
    isDead = FALSE;
    direction = 0;
    isMoving = FALSE;
    movingDuration = 0;
};



/* **********************************************************************************************************************
   Copy Constructor
   **********************************************************************************************************************/

VDSprite::VDSprite(const VDSprite &copySprite) {
    texture = copySprite.texture;  // this is a COM object - TODO: I've been trying to figure out if this is safe
    sourceRectangle.left = copySprite.sourceRectangle.left;
    sourceRectangle.top = copySprite.sourceRectangle.top;
    sourceRectangle.right = copySprite.sourceRectangle.right;
    sourceRectangle.bottom = copySprite.sourceRectangle.bottom;
    center.x = copySprite.center.x;
    center.y = copySprite.center.y;
    center.z = copySprite.center.z;
    position.x = copySprite.position.x;
    position.y = copySprite.position.y;
    position.z = copySprite.position.z;
    color = copySprite.color;
    isStatic = copySprite.isStatic;
    isNPC = copySprite.isNPC;
    isDead = copySprite.isDead;
    direction = copySprite.direction;
    isMoving = copySprite.isMoving;
    movingDuration = copySprite.movingDuration;
};



/* **********************************************************************************************************************
   Destructor
   **********************************************************************************************************************/

VDSprite::~VDSprite() {
};



/* **********************************************************************************************************************
   Draw
   ----
   Draws the sprite.
   #param  sprite  Pointer to the sprite interface.
   **********************************************************************************************************************/

void VDSprite::Draw(LPD3DXSPRITE sprite) {
    HRESULT returnValue = NULL;

    // draw the sprite
    returnValue = sprite->Draw(texture, &sourceRectangle, NULL, &position, color);
    if (returnValue != S_OK) {
        VDDirectXError("Failed to draw the sprite.", returnValue, __FILE__, __LINE__);
    };
};



/* **********************************************************************************************************************
   ShiftLocation
   -------------
   Translates a sprite.
   #param  direct3DDevice  Pointer to the Direct3D interface.
   #param  x               X of how much to translate.
   #param  y               Y of how much to translate.
   **********************************************************************************************************************/

void VDSprite::ShiftLocation(LPDIRECT3DDEVICE9 direct3DDevice, float x, float y) {
    HRESULT returnValue = NULL;
    D3DXMATRIX translation;

    // set up the translation matrix
    (void) D3DXMatrixTranslation(&translation, x, y, 0.0f);

    // apply the translation to the world
    returnValue = direct3DDevice->SetTransform(D3DTS_WORLD, &translation);
    if (returnValue != D3D_OK) {
        VDDirectXError("Failed to set a single device transformation-related state.", returnValue, __FILE__, __LINE__);
    };
};



/* **********************************************************************************************************************
   MovingSprite
   ------------
   Tells the sprite that we're in the process of moving.
   #param  aDirection  Direction in which the sprite is moving.
   **********************************************************************************************************************/

void VDSprite::MovingSprite(int aDirection) {
    if (aDirection != 0) {
        direction = aDirection;
        isMoving = TRUE;
    };
};



/* **********************************************************************************************************************
   FreeTexture
   -----------
   Releases the texture interface.
   **********************************************************************************************************************/

void VDSprite::FreeTexture() {
    if (texture != NULL) {
        (void) texture->Release();
        texture = NULL;
    };
};



/* **********************************************************************************************************************
   Accessors and Modifiers
   **********************************************************************************************************************/

LPDIRECT3DTEXTURE9 VDSprite::GetTexture() {
    return texture;
};
LPRECT VDSprite::GetSourceRectangle(LPRECT outRect) {
    outRect->left = sourceRectangle.left;
    outRect->top = sourceRectangle.top;
    outRect->right = sourceRectangle.right;
    outRect->bottom = sourceRectangle.bottom;

    return &sourceRectangle;
};

void VDSprite::SetSourceRectangle(LONG left, LONG top, LONG right, LONG bottom) {
    sourceRectangle.left = left;
    sourceRectangle.top = top;
    sourceRectangle.right = right;
    sourceRectangle.bottom = bottom;
};

D3DXVECTOR3 VDSprite::GetPosition() {
    return position;
};

void VDSprite::AddToPosition(float x, float y) {
    position.x += x;
    position.y += y;
};

BOOL VDSprite::IsStatic() {
    return isStatic;
};

BOOL VDSprite::IsNPC() {
    return isNPC;
};

BOOL VDSprite::IsDead() {
    return isDead;
};

void VDSprite::KillSprite() {
    isDead = TRUE;
};

BOOL VDSprite::IsMoving() {
    return isMoving;
};

void VDSprite::SetIsMoving(BOOL isItMoving) {
    isMoving = isItMoving;
};

int VDSprite::GetDirection() {
    return direction;
};

void VDSprite::SetDirection(int aDirection) {
    direction = aDirection;
};

int VDSprite::GetMovingDuration() {
    return movingDuration;
};

void VDSprite::SetMovingDuration(int amount) {
    movingDuration = amount;
};

void VDSprite::AddToMovingDuration(int amount) {
    movingDuration += amount;
};

UINT VDSprite::GetSpriteWidth() {
    D3DSURFACE_DESC surface;
    HRESULT returnValue = texture->GetLevelDesc(0, &surface);
    if (FAILED(returnValue)) {
        VDDirectXError("Failed to get the surface description of the sprite.", returnValue, __FILE__, __LINE__);
    };

    return surface.Width;
};

UINT VDSprite::GetSpriteHeight() {
    D3DSURFACE_DESC surface;
    HRESULT returnValue = texture->GetLevelDesc(0, &surface);
    if (FAILED(returnValue)) {
        VDDirectXError("Failed to get the surface description of the sprite.", returnValue, __FILE__, __LINE__);
    };

    return surface.Height;
};