#include "cImage.hpp"

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

using VideoEngine::cImage;
using UtilityEngine::cUtility;

cImage::cImage( const cString& dir /*= ""*/, const cString& filename /*= ""*/, const bool transparent /*= false*/, 
			   const unsigned char red /*= 0*/, const unsigned char blue /*= 0*/, const unsigned char green /*= 255*/,
			   const unsigned char translevel /*= 255*/)
: mp_texture(nullptr), m_dir(dir), m_fileName(filename), m_transparent(transparent),
m_transRed(red), m_transBlue(blue), m_transGreen(green), m_transLevel(translevel)
{
	if (m_fileName != (char*)"")
		LoadImage();
	if (mp_texture != nullptr)
		TransparentSetup();
}

cImage::cImage( SDL_Surface* surface )
: mp_texture(nullptr), m_dir(""), m_fileName(""), m_transparent(false),
m_transRed(0), m_transBlue(0), m_transGreen(255), m_transLevel(255)
{
	setImage(surface);
}

cImage::cImage( SDL_Texture* texture )
	: mp_texture(nullptr), m_dir(""), m_fileName(""), m_transparent(false),
	m_transRed(0), m_transBlue(0), m_transGreen(255), m_transLevel(255)
{
	setImage(texture);
}

cImage::cImage( const cImage& copy, const bool surfaceCopy /*= true*/)
: mp_texture(nullptr), m_dir(copy.getDir()), 
m_fileName(copy.getFileName()), m_transparent(copy.getTransparent()), m_transRed(copy.getRedTrans()),
m_transBlue(copy.getBlueTrans()), m_transGreen(copy.getGreenTrans()), m_transLevel(copy.getLevelTrans())
{
	if (surfaceCopy == true)
		mp_texture = copy.getImage();
}

cImage::~cImage()
{
	UnloadImage();
}

///Functions
void cImage::SaveImage( const cString& fileName, const cString& dir /*= ""*/ )
{
	cRenderer::Inst().SaveTexture( mp_texture, fileName, dir );
}

const cImage* cImage::NewImage( SDL_Rect& area ) const
{
	cImage* rtn = new cImage(*this, false);

	SDL_Texture* tempTexture = cRenderer::Inst().NewTexture(area.w, area.h, SDL_TEXTUREACCESS_TARGET);

	if (tempTexture != nullptr) {
		cRenderer::Inst().RenderToTexture(tempTexture, nullptr, mp_texture, &area);
		rtn->setImage(tempTexture);
	} else
		cUtility::Inst().Message("No texture created.", __AT__);


	/*SDL_Surface* tempsurface = SDL_CreateRGBSurface(cVideo::Instance().getVideoSettings(), area.w, area.h, cVideo::Instance().getColour(),
		mp_texture->format->Rmask, mp_texture->format->Gmask, mp_texture->format->Bmask, mp_texture->format->Amask);
	cVideo::Instance().Render(tempsurface, nullptr, mp_texture, &area);
	rtn->setImage(tempsurface);*/

	return rtn;
}

///Sets
void cImage::setDir( const cString& dir )
{
	m_dir = dir;
}

void cImage::setFileName( const cString& filename )
{
	m_fileName = filename;
	LoadImage();
}

void cImage::setFileNameandDir( const cString& filename, const cString& dir /*= ""*/ )
{
	setDir(dir);
	setFileName(filename);
}

void cImage::setTransparent( const bool transparent /*= true*/ )
{
	m_transparent = transparent;
	TransparentSetup();	
}

void cImage::setColourTrans( const unsigned char red /*= 0*/, const unsigned char blue /*= 0*/, const unsigned char green /*= 255*/ )
{
	m_transRed = red;
	m_transBlue = blue;
	m_transGreen = green;
	TransparentSetup();
}

void cImage::setLevelTrans( const unsigned char translevel /*= 255*/ )
{
	m_transLevel = translevel;
}

///Gets
SDL_Surface* cImage::getSurface() const
{
	return cRenderer::Inst().TextureToSurface(mp_texture);
}

SDL_Texture* cImage::getImage() const
{
	return mp_texture;
}

const unsigned long int cImage::getWidth() const
{
	unsigned long int w = 0;
	unsigned long int h = 0;

	getWH(w, h);
	return w;
}

const unsigned long int cImage::getHeight() const
{
	unsigned long int w = 0;
	unsigned long int h = 0;

	getWH(w, h);
	return h;
}

const SDL_Rect cImage::getWH() const
{
	unsigned long int w = 0;
	unsigned long int h = 0;

	getWH(w, h);
	SDL_Rect rtn = { 0, 0, (int)w, (int)h};
	return rtn;
}

void cImage::getWH( unsigned long int& w, unsigned long int& h ) const
{
	int width = 0;
	int height = 0;
	if (mp_texture != nullptr)
		if (SDL_QueryTexture(mp_texture, nullptr, nullptr, &width, &height) < 0)
			cUtility::Inst().Message("Unable to get Width or Height. SDL_QueryTexture:", __AT__, cUtility::eTypeSDL::SDL);
	w = width;
	h = height;
}

const cString cImage::getDir() const
{
	return m_dir;
}

const cString cImage::getFileName() const
{
	return m_fileName;
}

const bool cImage::getTransparent() const
{
	return m_transparent;
}

void cImage::getColourTrans( unsigned char& red, unsigned char& blue, unsigned char& green ) const
{
	red = m_transRed;
	blue = m_transBlue;
	green = m_transGreen;
}

const unsigned char cImage::getRedTrans() const
{
	return m_transRed;
}

const unsigned char cImage::getBlueTrans() const
{
	return m_transBlue;
}

const unsigned char cImage::getGreenTrans() const
{
	return m_transGreen;
}

const unsigned char cImage::getLevelTrans() const
{
	return m_transLevel;
}

//protected:
void cImage::setImage( SDL_Surface* surface )
{
	UnloadImage();

	mp_texture = cRenderer::Inst().SurfaceToTexture(surface);

	SDL_FreeSurface(surface);
}

void cImage::setImage( SDL_Texture* texture )
{
	UnloadImage();
	mp_texture = texture;
}

///private
///Functions
void cImage::TransparentSetup()
{
	if( (m_transparent == true) && (mp_texture != nullptr) ) {
		if ((SDL_SetTextureColorMod(mp_texture,  m_transRed, m_transGreen, m_transBlue) | SDL_SetTextureAlphaMod(mp_texture, m_transLevel)) < 0)
			cUtility::Inst().Message("Unable to set Transparent. SDL_SetTextureColorMod:", __AT__, cUtility::eTypeSDL::SDL);
	}
	//LoadImage();
}

void cImage::LoadImage()
{
	UnloadImage();
	
	SDL_Texture* tempText = nullptr;

	if (m_fileName != "")
	{
		cString temp = m_dir + m_fileName;

		if ((tempText = IMG_LoadTexture( cRenderer::Inst().getRenderer(), temp.c_str() )) == nullptr)
			cUtility::Inst().Message("Unable to load necessary image file. " + temp + " IMG_LoadTexture():", __AT__, cUtility::eTypeSDL::IMAGE);
	}
}

void cImage::UnloadImage()
{
	if (mp_texture != nullptr)
	{
		SDL_DestroyTexture(mp_texture);
		mp_texture = nullptr;
	}
}


