/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/sgx/graphics/texture.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"

CSGXTexture::CSGXTexture()
{
	m_pSurface = NULL;
	m_Transparent = FALSE;
	m_Translucent = FALSE;
}

CSGXTexture::~CSGXTexture() {
	//delete m_pSurface;
	m_pSurface = NULL;
}

void 
CSGXTexture::set() const
{
	if (m_pSurface) {
		m_pSurface->set();
	}
}

void	
CSGXTexture::setWrapped(const tWrapped wrapped)
{
	if (m_pSurface) {
		m_pSurface->setWrapped(wrapped);
	}
}

tUINT32 
CSGXTexture::getWidth() const
{
	if (m_pSurface) {
		return m_pSurface->getWidth();
	}
	return 0;
}

tUINT32 
CSGXTexture::getHeight() const
{
	if (m_pSurface) {
		return m_pSurface->getHeight();
	}
	return 0;
}

void 
CSGXTexture::setRegion(const tUINT32 region)
{
	if (m_pSurface) {
		m_pSurface->setRegion(region);
	}
}

void 
CSGXTexture::setRegion(const sgxUV &uv)
{
	if (m_pSurface) {
		m_pSurface->setRegion(uv);
	}
}

void 
CSGXTexture::clearRegions()
{
	m_Region.resize(0);
}

sgxRegion::sgxRegion() : sgxUV() {
}

sgxRegion::sgxRegion(const tUINT32 tw, const tUINT32 th, const sgxUV &uv) : sgxUV(uv) {
	width = (tUINT16)((u2-u1) * tw);
	height = (tUINT16)((v2-v1) * th);
}

sgxRegion::sgxRegion(const tUINT32 tw, const tUINT32 th, const tUINT32 x, const tUINT32 y, const tUINT32 x2, const tUINT32 y2) {
	u1 = tREAL32(x)/tw;
	v1 = tREAL32(y)/th;
	// We use the non-inclusive right hand edge
	u2 = tREAL32(x2)/tw;
	v2 = tREAL32(y2)/th;
	sgxAssert((x2-x) < 65536);
	sgxAssert((y2 - y) < 65536);
	width = (tUINT16)(x2-x);
	height = (tUINT16)(y2 - y);

}


tUINT32 
CSGXTexture::addRegion(const sgxUV &region)
{
	m_Region.push_back(sgxRegion(getWidth(), getHeight(), region));
	return m_Region.size()-1;
}

tUINT32 
CSGXTexture::addPixelRegion(const tUINT32 x, const tUINT32 y, const tUINT32 x2, const tUINT32 y2)
{
//	return addRegion(sgxUV(tREAL32(x)/getWidth(), tREAL32(y)/getHeight(), tREAL32(x2)/getWidth(), tREAL32(y2)/getHeight()));
	m_Region.push_back(sgxRegion(getWidth(), getHeight(), x,y,x2,y2));
	return m_Region.size()-1;
}

tUINT32 
CSGXTexture::addStd4Regions()
{
	tUINT32 firstNewRegion = m_Region.size();
	addStandardRegions(2, 2);
	return firstNewRegion;
}

tUINT32 
CSGXTexture::addStandardRegions(const tUINT32 regionsOnWidth, const tUINT32 regionsOnHeight)
{
	sgxAssert(regionsOnWidth && regionsOnHeight && "Must be at least one region per axis");
	tUINT32 firstNewRegion = m_Region.size();
	tUINT32 tw = getWidth();
	tUINT32 th = getHeight();
	tUINT32 rw = tw / regionsOnWidth;
	tUINT32 rh = th / regionsOnHeight;

//	tREAL32 dx=1/(tREAL32)regionsOnWidth;
//	tREAL32 dy=1/(tREAL32)regionsOnHeight;

	tUINT32 py1 = 0;
	tUINT32 py2 = rh-1;
	for(tUINT32 y=0;y<regionsOnHeight;++y) {
		tUINT32 px1 = 0;
		tUINT32 px2 = rw-1;
		for(tUINT32 x=0;x<regionsOnWidth;++x) {
			//sgxRegion(getWidth(), getHeight(), x,y,x2,y2
			m_Region.push_back(sgxRegion(tw,th, px1,py1, px2, py2));
				//sgxUV(x*dx,y*dy,x*dx+dx,y*dy+dy));
			px1 += rw;
			px2 += rw;
		}
		py1 += rh;
		py2 += rh;
	}
	return firstNewRegion;
}

tUINT32 
CSGXTexture::addRegionSizes(const tUINT32 w, const tUINT32 h)
{
	sgxAssert(w && h && "Must be at least one region per axis");
	tUINT32 firstNewRegion = m_Region.size();

	tUINT32 num_width = getWidth()/w;
	tUINT32 num_height = getHeight()/h;

	for(tUINT32 y=0;y<num_height;++y) {
		tUINT32 ry1 = y*w;
		tUINT32 ry2 = (y*w)+h-1;
		for(tUINT32 x=0;x<num_width;++x) {
			addPixelRegion(x*w, ry1, x*w+(w-1), ry2);
//			tREAL32 rx=(x*w)/(tREAL32)getWidth();
			//m_Region.push_back(sgxUV(rx, ry, rx+tREAL32(w)/getWidth(), ry+tREAL32(h)/getHeight()));
		}
	}
	return firstNewRegion;
}

tUINT32	
CSGXTexture::getNumRegions() const
{
	return m_Region.size();
}

void	
CSGXTexture::getRegion(const tUINT32 region, sgxUV &uv) const
{
	sgxAssert(region >= 0 && region < getNumRegions());
	const sgxUV &uvr = m_Region[region];
	uv = uvr;
#if SGX_PLATFORM_NDS
#else
	uv.u1 += 0.5f/getWidth();//m_Width;
	uv.u2 -= 0.5f/getWidth();//m_Width;
	uv.v1 += 0.5f/getHeight();//m_Height;
	uv.v2 -= 0.5f/getHeight();//m_Height;
#endif
}

void	
CSGXTexture::getRegionSize(const sgxUV &uv, sgxDimension2i &size) const
{
	size.width = (tPOINT)((uv.u2-uv.u1) * getWidth());
	size.height = (tPOINT)((uv.v2-uv.v1) * getHeight());
}

tUINT32	
CSGXTexture::getRegionWidth(const tUINT32 region) const
{
	if (region >=0 && region < m_Region.size()) {
		return m_Region[region].width;
	} 
	return 0;
//	return (tPOINT)((m_Region[region].u2-m_Region[region].u1) * getWidth());
}

tUINT32	
CSGXTexture::getRegionHeight(const tUINT32 region) const
{
	return m_Region[region].height;
	//return (tPOINT)((m_Region[region].v2-m_Region[region].v1) * getHeight());
}

tUINT32	
CSGXTexture::getRegionWidth(const sgxUV &uv) const
{
	return (tPOINT)((uv.u2-uv.u1) * getWidth());
}


tUINT32	
CSGXTexture::getRegionHeight(const sgxUV &uv) const
{
	return (tPOINT)((uv.v2-uv.v1) * getHeight());
}

void	
CSGXTexture::getRegionSize(const tUINT32 region, sgxDimension2i &size) const
{
	size.width = getRegionWidth(region);
	size.height = getRegionHeight(region);
}

void	
CSGXTexture::getRegionArea(const tUINT32 region, sgxRect2i &rc) const
{
sgxUV uv;
	getRegion(region, uv);
	rc.left = (tPOINT)(uv.u1 * getWidth());
	rc.top = (tPOINT)(uv.v1 * getHeight());
	rc.right = rc.left + m_Region[region].width;
	rc.bottom = rc.top + m_Region[region].height;
//	rc.right = (tPOINT)(uv.u2 * getWidth());
	//rc.bottom = (tPOINT)(uv.v2 * getHeight());
}

void
CSGXTexture::rebuild(void *pBitmap)
{
	if (!m_pSurface) {
		return;
	}

	m_pSurface->rebuild(pBitmap);
}


void	*
CSGXTexture::getDynamicBitmap()
{
	if (!m_pSurface) {
		return NULL;
	}

	return m_pSurface->getDynamicBitmap();
}

tBOOL	
CSGXTexture::getDynamicImageData(CImageData &data) const
{
	if (!m_pSurface) {
		return NULL;
	}

	return m_pSurface->getDynamicImageData(data);
}

void
CSGXTexture::setBlendMode(const tBlendMode mode) 
{
	if (!m_pSurface) {
		return;
	}

	m_pSurface->setBlendMode(mode);
}

tBOOL
CSGXTexture::setTextureProperty(const sgxString &property, const sgxTexturePropertyParams *pParams)
{
	SGX_UNUSED(property);
	SGX_UNUSED(pParams);
	// FALSE indicates this property is not supported.
	if (!m_pSurface) {
		return FALSE;
	}
//TODO
	//m_pSurface->setTextureProperty(property, pParams);

	return TRUE;
	
}



