#include "standard.h"
#include "global.h"
#include "debug.h"
#include "winmain.h"
#include "texture.h"
#include <math.h>
#include "drawprimitive.h"
#include "init.h"
#include "utils.h"
#include "hwrender.h"

/*** defines ***/
#define BGND_TPAGES 5

/*** typedefs ***/

/*** globals ***/

/*** locals ***/
local int LanTextureHandle[BGND_TPAGES];
local DWORD LahD3DTH[BGND_TPAGES];
local int LhPalette=-1;
local bool LtPictureLoaded;

/*** code ***/

local void AddTexture(int nTPage,uint8* pTPage,int hPalette,uint8* pPalette)
	{
	int nHandle;

//	if (hPalette>=0)
//		nHandle=DXTextureAddPal(256,256,pTPage,hPalette);
//	else
		{
		uint16* pTP16;
		uint8 bPix,*pPE;
		int i;

		pTP16=(uint16*)(pTPage+0x20000);
		pTPage+=0x10000;
		for (i=0x10000;i--;)
			{
			bPix=*(--pTPage);
			pPE=pPalette+(bPix*3);
			*(--pTP16)=0x8000|((pPE[0]>>3)<<10)|((pPE[1]>>3)<<5)|(pPE[2]>>3);
			}
//		nHandle=DXTextureAdd(256,256,(uint16*)pTPage);
		}
	if (nHandle>=0)
		{
		LanTextureHandle[nTPage]=nHandle;
		Log("Added bgnd tpage %d (handle=%d)",nTPage,nHandle);
		}
	else
		{
		LanTextureHandle[nTPage]=-1;
		Log("Failed to add bgnd tpage %d",nTPage);
		}
	}

local void FreeTextures(void)
	{
	int nHandle;
/*
	for (int nTexture=0;nTexture<ArraySize(LanTextureHandle);++nTexture)
		{
		nHandle=LanTextureHandle[nTexture];
		if (nHandle>=0)
			{
			DXTextureFree(nHandle);
			LanTextureHandle[nTexture]=-1;
			Log("Freed bgnd tpage %d",nTexture);
			}
		LahD3DTH[nTexture]=0;
		}
	if (LhPalette>=0)
		{
		DXTextureFreePalette(LhPalette);
		LhPalette=-1;
		}
*/
  
}

local void GetAllTextureHandles(void)
	{

	/*
	for (int nTPage=0;nTPage<ArraySize(LanTextureHandle);++nTPage)
		{
		int nHandle=LanTextureHandle[nTPage];
		if (nHandle>=0)
			LahD3DTH[nTPage]=DXTextureGetHandle(nHandle);
		else
			LahD3DTH[nTPage]=0;
		}
	*/
  
	}

void BGND_Make640x480(uint8* pImage,uint8* pPalette)
	{
	uint8* pTPage;

//	if (G_TextureSettings.nBPP<16)			// RF
//		LhPalette=TX_NewPalette(pPalette);
//	else
		LhPalette=-1;

	pTPage=(uint8*)game_malloc(0x20000,TEMP_ALLOC);

	UT_MemBlt(pTPage,0,0,256,256,256,pImage,0,0,640);
	AddTexture(0,pTPage,LhPalette,pPalette);
	UT_MemBlt(pTPage,0,0,256,256,256,pImage,256,0,640);
	AddTexture(1,pTPage,LhPalette,pPalette);
	UT_MemBlt(pTPage,0,0,128,256,256,pImage,512,0,640);
	UT_MemBlt(pTPage,128,0,128,224,256,pImage,512,256,640);
	AddTexture(2,pTPage,LhPalette,pPalette);
	UT_MemBlt(pTPage,0,0,256,224,256,pImage,0,256,640);
	AddTexture(3,pTPage,LhPalette,pPalette);
	UT_MemBlt(pTPage,0,0,256,224,256,pImage,256,256,640);
	AddTexture(4,pTPage,LhPalette,pPalette);

	game_free(0x20000,TEMP_ALLOC);
	GetAllTextureHandles();
	LtPictureLoaded=true;
	}

local void DrawTextureTile(int nDX,int nDY,int nDW,int nDH,int hTPage,int nSX,int nSY,int nSW,int nSH,uint32 dwV0C,uint32 dwV1C,uint32 dwV2C,uint32 dwV3C)
	{
	D3DTLVERTEX v[4];
	float fX1,fY1,fX2,fY2;
	float fU1,fV1,fU2,fV2;
	float fZ,fRHW;

	fX1=float(nDX);
	fY1=float(nDY);
	fX2=float(nDX+nDW);
	fY2=float(nDY+nDH);
	fU1=float(nSX)*(1.0f/256.0f);
	fV1=float(nSY)*(1.0f/256.0f);
	fU2=float(nSX+nSW)*(1.0f/256.0f);
	fV2=float(nSY+nSH)*(1.0f/256.0f);
	float fAdd= float(App.nUVAdd)*(1.0f/65536.0f);
	//Log("%f",fAdd);
	fU1+=fAdd;
	fV1+=fAdd;
	fU2-=fAdd;
	fV2-=fAdd;
	fZ=0.995f;
	fRHW=one/f_zfar;
	v[0].sx=fX1; v[0].sy=fY1; v[0].sz=fZ; v[0].rhw=fRHW; v[0].color=dwV0C; v[0].specular=0; v[0].tu=fU1; v[0].tv=fV1;
	v[1].sx=fX2; v[1].sy=fY1; v[1].sz=fZ; v[1].rhw=fRHW; v[1].color=dwV1C; v[1].specular=0; v[1].tu=fU2; v[1].tv=fV1;
	v[2].sx=fX1; v[2].sy=fY2; v[2].sz=fZ; v[2].rhw=fRHW; v[2].color=dwV2C; v[2].specular=0; v[2].tu=fU1; v[2].tv=fV2;
	v[3].sx=fX2; v[3].sy=fY2; v[3].sz=fZ; v[3].rhw=fRHW; v[3].color=dwV3C; v[3].specular=0; v[3].tu=fU2; v[3].tv=fV2;
	HWR_SetCurrentTexture(hTPage);
	HWR_EnableColorKey(false);
	
	DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
	}

local void DrawQuad(float fX,float fY,float fW,float fH,DWORD dwRGBA)
	{
	D3DTLVERTEX v[4];
	v[0].sx=fX; v[0].sy=fY;
	v[1].sx=fX+fW; v[1].sy=fY;
	v[2].sx=fX; v[2].sy=fY+fH;
	v[3].sx=fX+fW; v[3].sy=fY+fH;
	for (int nV=0;nV<4;++nV)
		{
		v[nV].sz=0.0f;
		v[nV].rhw=f_oneoznear;
		v[nV].color=dwRGBA|0xff000000;
		v[nV].specular=0;
		}
	HWR_SetCurrentTexture(0);
	HWR_EnableColorKey(false);
	
	DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
	}

void BGND_ClearToBlack()
	{
	HWR_EnableZBuffer(false,false);
	DrawQuad(float(phd_winxmin),float(phd_winymin),float(phd_winwidth),float(phd_winheight),0);
	HWR_EnableZBuffer(true,true);
	}

local uint32 CalcNiceOvalShade(int nX,int nY,int nW,int nH)
	{
	double dX=double(nX-(nW>>1))/double(nW);
	double dY=double(nY-(nH>>1))/double(nH);
	double dR=sqrt(dX*dX+dY*dY);
	int nRet=256-(int)(dR*300.0);
	if (nRet<0)
		nRet=0;
	else if (nRet>0xff)
		nRet=0xff;
	return nRet|(nRet<<8)|(nRet<<16)|0xff000000;
	}


#define MENU_BACKGROUND 0

void BGND_DrawInGameBackground()
	{
	if (!objects[MENU_BACKGROUND].loaded)
		{
		BGND_ClearToBlack();
		return;
		}
	int nMesh=objects[MENU_BACKGROUND].mesh_index;
	sint16* pMesh=meshes[nMesh];
	pMesh+=5;
	int nVertices=*pMesh++;
	pMesh+=(3*nVertices);
	nVertices=*pMesh++;
	if (nVertices>=0)
		pMesh+=3*nVertices;
	else
		pMesh+=nVertices;
	PHDTEXTURESTRUCT* pTex=phdtextinfo+pMesh[1+4];

	int hTexture=GahTextureHandle[pTex->tpage];
	int nTU=(pTex->u1)>>8;
	int nTV=(pTex->v1)>>8;
	int nTW=((pTex->u3>>8)+1)-nTU;
	int nTH=((pTex->v3>>8)+1)-nTV;
	int nW=phd_winwidth;
	int nH=phd_winheight;
	HWR_EnableZBuffer(false,false);
	for (int nY=0;nY<6;++nY)
		for (int nX=0;nX<8;++nX)
			{
			int nX1=((nX*nW)/8)+phd_winxmin;
			int nY1=((nY*nH)/6)+phd_winymin;
			int nX2=(((nX*nW)+nW)/8)+phd_winxmin;
			int nY2=(((nY*nH)+nH)/6)+phd_winymin;
			uint32 dwV0C=CalcNiceOvalShade(nX1,nY1,nW,nH);
			uint32 dwV1C=CalcNiceOvalShade(nX2,nY1,nW,nH);
			uint32 dwV2C=CalcNiceOvalShade(nX1,nY2,nW,nH);
			uint32 dwV3C=CalcNiceOvalShade(nX2,nY2,nW,nH);
			DrawTextureTile(nX1,nY1,nX2-nX1,nY2-nY1,hTexture,nTU,nTV,nTW,nTH,dwV0C,dwV1C,dwV2C,dwV3C);
			}
	HWR_EnableZBuffer(true,true);
	}

void BGND_Draw(void)
	{
	static int anVirtualX[4]={0,256,512,640},anVirtualY[3]={0,256,480};
	int anX[4],anY[4];
	int nW,nH,nCoord;

	if (!LtPictureLoaded)
		{
		BGND_DrawInGameBackground();
		return;
		}
	GetAllTextureHandles();
	nW=phd_winwidth;	//G_RenderInfo.nWidth;
	nH=phd_winheight;	//G_RenderInfo.nHeight;

	for (nCoord=0;nCoord<3;++nCoord)
		{
		anX[nCoord]=(anVirtualX[nCoord]*nW)/640+phd_winxmin;
		anY[nCoord]=(anVirtualY[nCoord]*nH)/480+phd_winymin;
		}
	anX[3]=(anVirtualX[3]*nW)/640+phd_winxmin;
	HWR_EnableZBuffer(false,false);
	DrawTextureTile(anX[0],anY[0],anX[1]-anX[0],anY[1]-anY[0],LahD3DTH[0],0,0,256,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTextureTile(anX[1],anY[0],anX[2]-anX[1],anY[1]-anY[0],LahD3DTH[1],0,0,256,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTextureTile(anX[2],anY[0],anX[3]-anX[2],anY[1]-anY[0],LahD3DTH[2],0,0,128,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTextureTile(anX[0],anY[1],anX[1]-anX[0],anY[2]-anY[1],LahD3DTH[3],0,0,256,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTextureTile(anX[1],anY[1],anX[2]-anX[1],anY[2]-anY[1],LahD3DTH[4],0,0,256,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTextureTile(anX[2],anY[1],anX[3]-anX[2],anY[2]-anY[1],LahD3DTH[2],128,0,128,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	HWR_EnableZBuffer(true,true);
	}

void BGND_Free(void)
	{
	FreeTextures();
	LtPictureLoaded=false;
	}

bool BGND_Init(void)
	{
	Log(LT_Enter,"HWR_Init");
	for (int nTexture=0;nTexture<ArraySize(LanTextureHandle);++nTexture)
		LanTextureHandle[nTexture]=-1;
	LhPalette=-1;
	LtPictureLoaded=false;
	return true;
	}
