#include "cSprite.hpp"

/*** Custom Header Files ***/
#include "cRenderer.hpp"

using VideoEngine::cSprite;
using MathEngine::iVector2;
using MathEngine::iVector4;

cSprite::cSprite( const signed long int xpos /*= 0*/, const signed long int ypos /*= 0*/, const signed long int xarea /*= 0*/,
				 const signed long int yarea /*= 0*/, const unsigned long int warea /*= 0*/, const unsigned long int harea /*= 0*/,
				 VideoEngine::cImage** image /*= nullptr*/, VideoEngine::cCamera** camera /*= nullptr*/ )
: mpp_image(image), mpp_camera(camera)
{
	setPosition(Sint16(xpos), Sint16(ypos));

	setStartImageArea(Sint16(xarea), Sint16(yarea));
	setEndImageArea(Uint16(warea), Uint16(harea));
}

cSprite::cSprite( VideoEngine::cImage** image, VideoEngine::cCamera** camera /*= nullptr*/ )
: mpp_image(image), mpp_camera(camera)
{
	setPosition(0, 0);

	setStartImageArea(0, 0);
	setEndImageArea(Uint16((*mpp_image)->getWidth()), Uint16((*mpp_image)->getHeight()));
}

//cSprite::cSprite( TextTypeEngine::cText** image, VideoEngine::cCamera** camera /*= nullptr*/ )
/*:  mpp_camera(camera)
{
	image;
	//VideoEngine::cImage* im = VideoEngine::cImage(*image);
	setPosition(0, 0);

	setStartImageArea(0, 0);
	setEndImageArea(Uint16((*mpp_image)->getWidth()), Uint16((*mpp_image)->getHeight()));
}*/

cSprite& cSprite::operator=( const cSprite& copy )
{
	if (this != &copy)
	{
		mpp_image = nullptr;
		mpp_camera = nullptr;

		signed long int x = 0;
		signed long int y = 0;

		unsigned long int h = 0;
		unsigned long int w = 0;

		copy.getPosition(x, y);
		setPosition(x, y);

		copy.getStartImageArea(x, y);
		copy.getEndImageArea(w, h);

		setStartImageArea(x, y);
		setEndImageArea(w, h);

		*mpp_image = copy.getImage();
		*mpp_camera = copy.getCamera();
	}

	return *this;
}

cSprite::~cSprite()
{
	mpp_image = nullptr;
	mpp_camera = nullptr;
}

///Functions
void cSprite::Draw()
{ 
	SDL_Texture* texture = (*mpp_image)->getImage();

	if (mpp_camera != nullptr && *mpp_camera != nullptr) {
		CameraDraw();
		//surface = (*mpp_camera)->getCameraView();
	}

	if (mpp_image != nullptr && *mpp_image != nullptr)
		cRenderer::Inst().Render( texture, &m_imageArea, &m_position);
}

void cSprite::CameraDraw()
{
	if ((mpp_image != nullptr) && (mpp_camera != nullptr) && (*mpp_image != nullptr) && (*mpp_camera != nullptr))
		cRenderer::Inst().RenderToTexture((*mpp_image)->getImage(), &m_imageArea, (*mpp_camera)->getCameraView(), &m_position);
		//RendererDraw( (*mpp_camera)->getCameraView() );
}
// 
// void cSprite::RendererDraw( SDL_Renderer* rend )
// {
// 	cVideo::Instance().RenderToTexture()
// 	if ((rend != nullptr) && (mpp_image != nullptr) && (*mpp_image != nullptr))
// 		Video::Instance().Render((*mpp_image)->getImage(), &m_imageArea, rend, &m_position);
// }

void cSprite::DefaltDraw()
{
	if (mpp_image != nullptr && *mpp_image != nullptr)
		cRenderer::Inst().Render( (*mpp_image)->getImage(), nullptr, nullptr);
}

void cSprite::AddPosX( const signed long int x )
{
	m_position.x += Sint16(x);
}

void cSprite::AddPosY( const signed long int y )
{
	m_position.y += Sint16(y);
}

void cSprite::SaveImage( const cString& fileName, const cString& dir /*= ""*/ )
{
	if (mpp_image != nullptr && *mpp_image != nullptr) {
		SDL_Texture* temp = (*mpp_image)->getImage();//(*mpp_image)->NewImage(this->getImageArea())->getImage();

		cRenderer::Inst().SaveTexture( temp, fileName, dir );
	}
}

///Sets
void cSprite::setPosX( const signed long int x )
{
	setPosition( x, getPosY());
}

void cSprite::setPosY( const signed long int y )
{
	setPosition( getPosX(), y );
}

void cSprite::setPosition( const signed long int x, const signed long int y )
{
	m_position.x = (signed short int)x;
	m_position.y = (signed short int)y;
	setPositionEnd();
}

void cSprite::setPosition( const MathEngine::iVector2& position /*= MathEngine::iVector2(0,0)*/ )
{
	setPosition(position.x, position.y);
}

void cSprite::setImageArea( const MathEngine::iVector4& area /*= MathEngine::iVector4(0,0,0,0)*/)
{
	if (area == iVector4(0,0,0,0)) {
		setStartImageArea(0,0);
		if ((mpp_image != nullptr) && (*mpp_image != nullptr))
			setEndImageArea((*mpp_image)->getWidth(), (*mpp_image)->getHeight());
	} else {
		setStartImageArea( area.x, area.y );
		setEndImageArea( area.z, area.w );
	}
}

/// Top left starting area.
void cSprite::setStartImageArea( const signed long int x, const signed long int y )
{
	m_imageArea.x = (signed short int)x;
	m_imageArea.y = (signed short int)y;
}

/// Bottom right image ends.
void cSprite::setEndImageArea( const unsigned long int w, const unsigned long int h )
{
	m_imageArea.w = (unsigned short int)w;
	m_imageArea.h = (unsigned short int)h;

	setPositionEnd();
}

void cSprite::setImage( VideoEngine::cImage** image )
{
	mpp_image = image;
}

void cSprite::setCamera( VideoEngine::cCamera** camera )
{
	mpp_camera = camera;
}

///Get's
const signed long int cSprite::getPosX() const
{
	return m_position.x;
}

const signed long int cSprite::getPosY() const
{
	return m_position.y;
}

void cSprite::getPosition( signed long int& x, signed long int& y ) const
{
	x = m_position.x;
	y = m_position.y;
}

const MathEngine::iVector4 cSprite::getPosition() const
{
	return iVector4(m_position);
}

void cSprite::getStartImageArea( signed long int& x, signed long int& y ) const
{
	x = m_imageArea.x;
	y = m_imageArea.y;
}

void cSprite::getEndImageArea( unsigned long int& w, unsigned long int& h ) const
{
	w = m_imageArea.w;
	h = m_imageArea.h;
}

const SDL_Rect& cSprite::getImageArea() const
{
	return m_imageArea;
}

const unsigned long int cSprite::getWidth() const
{
	return m_imageArea.w;
}

const unsigned long int cSprite::getHeight() const
{
	return m_imageArea.h;
}

VideoEngine::cImage* cSprite::getImage() const
{
	if (mpp_image == nullptr)
		return nullptr;
	else
		return (*mpp_image);
}

VideoEngine::cCamera* cSprite::getCamera() const
{
	if (mpp_camera == nullptr)
		return nullptr;
	else
		return (*mpp_camera);
}

const bool cSprite::getImageSetup() const
{
	bool rtn = false;
	if ((mpp_image != nullptr) && (*mpp_image != nullptr))
		rtn = true;

	return rtn;
}

const bool cSprite::getCameraSetup() const
{
	bool rtn = false;
	if ((mpp_camera != nullptr) && (*mpp_camera != nullptr))
		rtn = true;

	return rtn;
}

void cSprite::setPositionEnd()
{
	m_position.w = m_imageArea.w;
	m_position.h = m_imageArea.h;
}