#include "sprite.h"

namespace CBK
{
	namespace Shapes
	{
		Sprite::Sprite(const MeshParam& params, const std::string& image) : Mesh(params, image)
		{
			if (getTextureLoader() != 0)
				_image = getTextureLoader()->load(image, _device);
			else
				_image = 0;

			D3DXCreateSprite(_device, &_sprite);

			_imageArea = 0;
			_position = 0;

			_color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
			_center = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

			_flags = D3DXSPRITE_OBJECTSPACE | D3DXSPRITE_ALPHABLEND;
		}

		Sprite::~Sprite(void)
		{
			if (getTextureLoader() != 0)
				if (_image != 0)
					getTextureLoader()->unload(_image);

			_sprite->Release();

			if (_imageArea != 0)
				delete _imageArea;

			if (_position != 0)
				delete _position;
		}

		item& Sprite::load(const std::string& name, const MeshParam& params)
		{
			setDevice(params.device);
			setTextureLoader(params.textureLoader);

			return *this;
		}

		Sprite& Sprite::setTransform(const D3DXMATRIX& transform)
		{
			_transform = transform;
			D3DXMATRIX s, rX, rY, rZ;

			D3DXMatrixScaling(&s, 0.1f, 0.1f, 0.1f);
			D3DXMatrixRotationX(&rX, 3.1415926535f * 1.5f);
			D3DXMatrixRotationY(&rY, 3.1415926535f * 1.5f);
			D3DXMatrixRotationZ(&rZ, 3.1415926535f * 0.0f);
			s = rY * rX * rZ * s * transform;

			_sprite->SetTransform(&s);
			return *this;
		}

		void Sprite::draw(const DWORD&)
		{
			D3DXMATRIX i;
			D3DXMatrixIdentity(&i);
//			_flags |= D3DXSPRITE_BILLBOARD;
//			_device->SetTransform(D3DTS_WORLDMATRIX(0), &_transform);
//			_sprite->SetTransform(&i);
			_sprite->Begin(_flags);
			_color = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
			_sprite->Draw(_image->getTexture(), _imageArea, &_center, _position, _color);
			_sprite->End();
		}

		void Sprite::apply(void)
		{
			draw();
		}

		Sprite& Sprite::setColor(const D3DCOLOR& color)
		{
			_color = color;

			return *this;
		}

		Sprite& Sprite::setColor(const float& r, const float& g, const float& b, const float& a)
		{
			_color = D3DXCOLOR(r, g, b, a);

			return *this;
		}

		const D3DCOLOR& Sprite::getColor(void) const
		{
			return _color;
		}

		Sprite& Sprite::setCenter(const D3DXVECTOR3& center)
		{
			_center = center;
			
			return *this;
		}

		Sprite& Sprite::setCenter(const float& x, const float& y, const float& z)
		{
			_center = D3DXVECTOR3(x, y, z);
			
			return *this;
		}

		const D3DXVECTOR3& Sprite::getCenter(void) const
		{
			return _center;
		}

		Sprite& Sprite::setImageArea(const RECT& imageArea)
		{
			if (_imageArea == 0)
				_imageArea = new RECT();

			*_imageArea = imageArea;
			
			return *this;
		}

		Sprite& Sprite::setImageArea(const long& left, const long& top, const long& right, const long& bottom)
		{
			if (_imageArea == 0)
				_imageArea = new RECT();

			_imageArea->left = left;
			_imageArea->top = top;
			_imageArea->right = right;
			_imageArea->bottom = bottom;

			return *this;
		}

		Sprite& Sprite::clearImageArea(void)
		{
			if (_imageArea != 0)
			{
				delete _imageArea;
				_imageArea = 0;
			}
			
			return *this;
		}

		const RECT* const Sprite::getImageArea(void) const
		{
			return _imageArea;
		}

		Sprite& Sprite::setImage(const std::string& image)
		{
			if (getTextureLoader() == 0) return *this;
			
			if (_image != 0)
				getTextureLoader()->unload(_image);

			_image = getTextureLoader()->load(image, _device);
			return *this;
		}

		Texture* Sprite::getImage(void) const
		{
			return _image;
		}

		Sprite& Sprite::setTextureLoader(textureFactory* textureLoader)
		{
			std::string name;
			bool wasLoaded;

			if (_image != 0)
			{
				name = _image->getName();
				wasLoaded = true;
				if (getTextureLoader() != 0)
				{
					getTextureLoader()->unload(name);
				}
			}
			else wasLoaded = false;

			Mesh::setTextureLoader(textureLoader);
			if (wasLoaded)
				_image = getTextureLoader()->load(name, _device);
			
			return *this;
		}

		const ID3DXSprite* const Sprite::getSprite(void) const
		{
			return _sprite;
		}

		Sprite& Sprite::enableWorldSpace(const bool enabled)
		{
			if (enabled)
				_flags |= D3DXSPRITE_OBJECTSPACE;
			else
				_flags &= ~D3DXSPRITE_OBJECTSPACE;
			
			return *this;
		}

		Sprite& Sprite::disableWorldSpace(void)
		{
			return enableWorldSpace(false);
		}

		const bool Sprite::getIsWorldSpace(void) const
		{
			return ((_flags & D3DXSPRITE_OBJECTSPACE) == D3DXSPRITE_OBJECTSPACE);
		}

		Sprite& Sprite::enableBillBoard(const bool enabled)
		{
			if (enabled)
				_flags |= D3DXSPRITE_BILLBOARD;
			else
				_flags &= ~D3DXSPRITE_BILLBOARD;
			
			return *this;
		}

		Sprite& Sprite::disableBillBoard(void)
		{
			return enableBillBoard(false);
		}

		const bool Sprite::getIsBillBoard(void) const
		{
			return ((_flags & D3DXSPRITE_BILLBOARD) == D3DXSPRITE_BILLBOARD);
		}

		Sprite& Sprite::setPosition(const float& x, const float& y, const float& z)
		{
			if (_position == 0)
				_position = new D3DXVECTOR3();

			_position->x = x;
			_position->y = y;
			_position->z = z;

			return *this;
		}

		Sprite& Sprite::setPosition(const D3DXVECTOR3& position)
		{
			if (_position == 0)
				_position = new D3DXVECTOR3();

			*_position = position;

			return *this;
		}

		Sprite& Sprite::clearPosition(void)
		{
			if (_position != 0)
			{
				delete _position;
				_position = 0;
			}

			return *this;
		}

		const D3DXVECTOR3* const Sprite::getPosition(void) const
		{
			return _position;
		}
	}
}