/******************************************************************************************
	AM2 PS   (c) 2000-1 ISL		-=Modified for Chicken Run=-

	language.c:		Language selection
******************************************************************************************/

#include "global.h"
#include "main.h"
#include "language.h"
#include "menu.h"
#include "card.h"
#include "overlays.h"
#include "startup.h"
#include "maths.h"
#include "custom.h"
#include "sound.h"
#include "options.h"

// RFW - changed from permanant arrays to a malloc
LanguageDataType *languageData = NULL;

#ifdef _WINDOWS
extern int scrOffsetX, scrOffsetY;
#endif

extern int stickleft;
extern int stickright;
extern int	gameTextLang;

static char *flagName[] =
{
	"UK",
	"FRENCH",
	"GERMANY",
	"ITALY",
};

extern void startupDraw(void);
extern void startupCycle(void);
extern short menuVidKeyhandler(void);

TextureBankType *languagebank;
TextureType *langarrowspr;

//static char enable;

static void setCamera(int vpx,int vpy,int vpz, int vrx,int vry,int vrz)
{
	GsSetProjection(650);
	languageData->langCam.vpx = vpx;
	languageData->langCam.vpy = vpy;
	languageData->langCam.vpz = vpz;
	languageData->langCam.vrx = vrx;
	languageData->langCam.vry = vry;
	languageData->langCam.vrz = vrz;
	GsSetRefView2L(&languageData->langCam);
  	SetGeomOffset(0, 0);
}

static void languageTransformPoints(void)
{
	long loop1, loop2;

	gte_SetRotMatrix(&GsWSMATRIX);
	gte_SetTransMatrix(&GsWSMATRIX);
	
	for(loop1 = 0; loop1 < FLAGPOINTS; loop1 ++)
	{
		for(loop2 = 0; loop2 < FLAGPOINTS; loop2 += 3)
		{
			gte_ldv3(&languageData->flagPoints[loop1][loop2], &languageData->flagPoints[loop1][loop2 + 1], &languageData->flagPoints[loop1][loop2 + 2]);
			gte_rtpt();
			gte_stsxy3(&languageData->screenXYs[loop1][loop2], &languageData->screenXYs[loop1][loop2 + 1], &languageData->screenXYs[loop1][loop2 + 2]);
			gte_stsz3(&languageData->screenZs[loop1][loop2], &languageData->screenZs[loop1][loop2 + 1], &languageData->screenZs[loop1][loop2 + 2]);
/*
#ifdef _WINDOWS
			((SHORTXY*)&languageData->screenXYs[loop1][loop2])->x += scrOffsetX;
			((SHORTXY*)&languageData->screenXYs[loop1][loop2])->y += scrOffsetY;

			((SHORTXY*)&languageData->screenXYs[loop1][loop2+1])->x += scrOffsetX;
			((SHORTXY*)&languageData->screenXYs[loop1][loop2+1])->y += scrOffsetY;

			((SHORTXY*)&languageData->screenXYs[loop1][loop2+2])->x += scrOffsetX;
			((SHORTXY*)&languageData->screenXYs[loop1][loop2+2])->y += scrOffsetY;
#endif
*/
		}
	}
}

static void languageDrawPolys(void)
{
	long		loop1, loop2;
	uchar		rgb;
	POLY_GT4	*gt4;
	POLY_GT4	*gt42;

	languageDrawBackground();
	for(loop1 = 0; loop1 < FLAGPOLYS; loop1 ++)
	{
		for(loop2 = 0; loop2 < FLAGPOLYS; loop2 ++)
		{
			BEGINPRIM(gt4, POLY_GT4);
			setPolyGT4(gt4);
			gt4->tpage = languageData->flagTexture[languageData->tileTexture]->tpage;
			gt4->clut = languageData->flagTexture[languageData->tileTexture]->clut;

			*(long *)&gt4->x0 = *(long *)&languageData->screenXYs[loop1][loop2];
			*(long *)&gt4->x1 = *(long *)&languageData->screenXYs[loop1][loop2 + 1];
			*(long *)&gt4->x2 = *(long *)&languageData->screenXYs[loop1 + 1][loop2];
			*(long *)&gt4->x3 = *(long *)&languageData->screenXYs[loop1 + 1][loop2 + 1];

			gt4->r0 = languageData->flagShade[loop1][loop2];
			gt4->g0 = languageData->flagShade[loop1][loop2];
			gt4->b0 = languageData->flagShade[loop1][loop2];

			gt4->r1 = languageData->flagShade[loop1][loop2 + 1];
			gt4->g1 = languageData->flagShade[loop1][loop2 + 1];
			gt4->b1 = languageData->flagShade[loop1][loop2 + 1];

			gt4->r2 = languageData->flagShade[loop1 + 1][loop2];
			gt4->g2 = languageData->flagShade[loop1 + 1][loop2];
			gt4->b2 = languageData->flagShade[loop1 + 1][loop2];

			gt4->r3 = languageData->flagShade[loop1 + 1][loop2 + 1];
			gt4->g3 = languageData->flagShade[loop1 + 1][loop2 + 1];
			gt4->b3 = languageData->flagShade[loop1 + 1][loop2 + 1];

			gt4->u0 = languageData->textureU[loop1][loop2][0];
			gt4->v0 = languageData->textureV[loop1][loop2][0];

			gt4->u1 = languageData->textureU[loop1][loop2][1];
			gt4->v1 = languageData->textureV[loop1][loop2][1];

			gt4->u2 = languageData->textureU[loop1][loop2][2];
			gt4->v2 = languageData->textureV[loop1][loop2][2];

			gt4->u3 = languageData->textureU[loop1][loop2][3];
			gt4->v3 = languageData->textureV[loop1][loop2][3];

			if(languageData->finishing < 54)	// "languageData->finishing" runs from 0...64 at the end. We'll fade the flag out during the last 10
			{
				setSemiTrans(gt4, 1);
				SETSEMIPRIM(gt4, SEMITRANS_SEMI);
				ENDPRIM(gt4,100, POLY_GT4);
			}
			else
			{
// Pull the additive / subtractive stunt, so the flag fades as it approaches the camera rather than just cutting out.
				gt4->r0 = gt4->r0 * (64-languageData->finishing)/20;	// "20" not "10", because it was originally *SEMI* trans
				gt4->g0 = gt4->g0 * (64-languageData->finishing)/20;
				gt4->b0 = gt4->b0 * (64-languageData->finishing)/20;
				gt4->r1 = gt4->r1 * (64-languageData->finishing)/20;
				gt4->g1 = gt4->g1 * (64-languageData->finishing)/20;
				gt4->b1 = gt4->b1 * (64-languageData->finishing)/20;
				gt4->r2 = gt4->r2 * (64-languageData->finishing)/20;
				gt4->g2 = gt4->g2 * (64-languageData->finishing)/20;
				gt4->b2 = gt4->b2 * (64-languageData->finishing)/20;
				gt4->r3 = gt4->r3 * (64-languageData->finishing)/20;
				gt4->g3 = gt4->g3 * (64-languageData->finishing)/20;
				gt4->b3 = gt4->b3 * (64-languageData->finishing)/20;

				setSemiTrans(gt4, 1);
				SETSEMIPRIM(gt4, SEMITRANS_ADD);
				ENDPRIM(gt4,100, POLY_GT4);

// subtractive underlay
				BEGINPRIM(gt42, POLY_GT4);
				*gt42 = *gt4;
				gt42->clut = overlaySolidAlphaClut;
				gt42->tpage = (gt42->tpage & (~(3<<5))) | ((SEMITRANS_SUB-1)<<5);
				ENDPRIM(gt42,100, POLY_GT4);
			}
		}
	}
}

void calculateTileTexture(int x, int y)
{
	if(languageData->tileTexture<LANG_NUMLANGS+1)
	{
		languageData->textureU[x][y][0] = languageData->textureU[x][y][1] = languageData->flagTexture[languageData->tileTexture]->u0
											  + ((languageData->flagTexture[languageData->tileTexture]->u3 + 1
											  - languageData->flagTexture[languageData->tileTexture]->u0)*x)/FLAGPOLYS + 1;
		languageData->textureU[x][y][2] = languageData->textureU[x][y][3] = languageData->flagTexture[languageData->tileTexture]->u0
											  + ((languageData->flagTexture[languageData->tileTexture]->u3 + 1
											  - languageData->flagTexture[languageData->tileTexture]->u0)*(x+1))/FLAGPOLYS + 1;

		languageData->textureV[x][y][0] = languageData->textureV[x][y][2] = languageData->flagTexture[languageData->tileTexture]->v0
											  + ((languageData->flagTexture[languageData->tileTexture]->v3 + 1 
											  - languageData->flagTexture[languageData->tileTexture]->v0)*y)/FLAGPOLYS + 1;
		languageData->textureV[x][y][1] = languageData->textureV[x][y][3] = languageData->flagTexture[languageData->tileTexture]->v0
											  + ((languageData->flagTexture[languageData->tileTexture]->v3 + 1
											  - languageData->flagTexture[languageData->tileTexture]->v0)*(y+1))/FLAGPOLYS + 1;
	}
	else
	{
		languageData->textureU[y][x][2] = languageData->textureU[y][x][0] = languageData->flagTexture[languageData->tileTexture]->u0
											  + ((languageData->flagTexture[languageData->tileTexture]->u3 
											  - languageData->flagTexture[languageData->tileTexture]->u0)*x)/FLAGPOLYS + 1;
		languageData->textureU[y][x][3] = languageData->textureU[y][x][1] = languageData->flagTexture[languageData->tileTexture]->u0
											  + ((languageData->flagTexture[languageData->tileTexture]->u3 
											  - languageData->flagTexture[languageData->tileTexture]->u0)*(x+1))/FLAGPOLYS + 1;

		languageData->textureV[y][x][1] = languageData->textureV[y][x][0] = languageData->flagTexture[languageData->tileTexture]->v0
											  + ((languageData->flagTexture[languageData->tileTexture]->v3 
											  - languageData->flagTexture[languageData->tileTexture]->v0)*y)/FLAGPOLYS + 1;
		languageData->textureV[y][x][3] = languageData->textureV[y][x][2] = languageData->flagTexture[languageData->tileTexture]->v0
											  + ((languageData->flagTexture[languageData->tileTexture]->v3 
											  - languageData->flagTexture[languageData->tileTexture]->v0)*(y+1))/FLAGPOLYS + 1;
	}
}

unsigned char* imagePtr;
#ifndef _WINDOWS
RECT tex;
#else
RECTPS tex;
#endif

TextureType face;

int language_cheatmode = 0;
#define LANG_CHEAT_TOLERANCE 400
/*
StrDataType blitz_vid_def =
{
	"\\BLITZ.STR;1",		//	char		*strName;					// Stream file name. ; Version number
	STR_MODE24,				//	short		mode;						// 24-Bit or 16-Bit streaming.
	STR_BORDERS_ON,			//	short		drawBorders;				// != 0 if borders on.
	320,					//	u_short		scrWidth;					// Screen res width.
	0,						//	u_short		x;							// X,Y position. 
#if(PALMODE==YES)
	8,						//	u_short		y;
#else
	0,
#endif
	320,					//	u_short		width;						// Stream width and height.
	240,					//	u_short		height;
	(140-3),				//	u_long		endFrame;					// Last frame No.
	0,						//	u_long		vlcBufSize;					// Size of each VLC buffer (including header) - 0 means use max.
	127						//	u_short		volume;						// Left and Right ADPCM volume.
};*/


void languageStart(void)
{
	long loop,loop1,loop2;


/*#if(GOLDCD==1)
	//----------------------------------------------------------------
	// Play the Blitz.str video

	static RECT VRAMarea1 = {0,0,512,256};
	static RECT VRAMarea2 = {0,256,512,256};

	ClearImage2(&VRAMarea1, 0,0,0);
	ClearImage2(&VRAMarea2, 0,0,0);

	videoPlayStream(&blitz_vid_def,PALMODE, &menuVidKeyhandler);
	//----------------------------------------------------------------
#endif*/


	language_cheatmode = 0;

	startupLoad();		// here rather than in startup, coz we need the plank texture

#if PALMODE==0
// NTSC doesn't have a language select
  #ifndef _WINDOWS
	sound_XA_Start(TUNE_1_INTRO);
	sound_XA_Queue(TUNE_5_COOPS_D);
  #endif
	cardPostLangStart();

#else
	languageData = MALLOC(sizeof(LanguageDataType));
	FMEMZERO(languageData,sizeof(LanguageDataType));

	languagebank = textureLoadBank("OPTIONS\\ARROWS.SPT");		// load all the sprites into RAM
	textureDownloadBank(languagebank);							// download it to VRAM
	textureDestroyBank(languagebank);							// and kill it in main RAM

	langarrowspr = textureFindInAllBanks("RARROW");

	draw_routine = languageDraw;
	cycle_routine = languageCycle;

	imagePtr=0;
	tex.x = 960;
	tex.y = 384;
	tex.w = 64;
	tex.h = 128;

	face.tpage = getTPage(2,0,960,256);
	face.clut = 0;
	face.u0 = 63; face.v0 = 128;
	face.u1 = 63; face.v1 = 255;
	face.u2 =  0; face.v2 = 128;
	face.u3 =  0; face.v3 = 255;


//	enable = 0;

	// setup stuff goes here, malloc memory or structs whatever
	languageData->flagTextures = textureLoadBank("FRONTEND\\LANGUAGE.SPT");
	for (loop = 0; loop < LANG_NUMLANGS-1; loop++)
		languageData->flagTexture[loop] = textureFindInBank(languageData->flagTextures,flagName[loop]);
	for (loop = LANG_NUMLANGS+1; loop < LANG_NUMLANGS+1+BONUS_FLAGS; loop++)
		languageData->flagTexture[loop] = &face;

	textureDestroyBank(languageData->flagTextures);
	languageData->frame = 0;
	languageData->lastFade = 0;



// ====== ALL LOADING NEEDS TO BE DONE BEFORE HERE! ======

  #ifndef _WINDOWS
	sound_XA_Start(TUNE_1_INTRO);
	sound_XA_Queue(TUNE_5_COOPS_D);
  #endif


	setCamera(0,-20000,0, 0,0,0);

	//Movement stuff
	for(loop = 0; loop < FLAGPOINTS; loop ++)
	{
		languageData->wind[loop] = 0;
		languageData->crosswind[loop] = 0;
	}

	//Position and movement stuff
	for(loop1 = 0; loop1 < FLAGPOINTS; loop1 ++)
	{
		for(loop2 = 0; loop2 < FLAGPOINTS; loop2 ++)
		{
			languageData->accel[loop1][loop2] = 0;
			languageData->flagPoints[loop1][loop2].vx = (loop1-FLAGPOINTS/2)*200;
			languageData->flagPoints[loop1][loop2].vy = (loop2-FLAGPOINTS/2)*100;
			if (loop1 > 0) 
				languageData->flagPoints[loop1][loop2].vz = loop1-loop2;
			else
				languageData->flagPoints[loop1][loop2].vz = 0;
		}
	}

	languageData->tileTexture = gameTextLang;
	for(loop1 = 0; loop1 < FLAGPOLYS; loop1 ++)
		for(loop2 = 0; loop2 < FLAGPOLYS; loop2 ++)
			calculateTileTexture(loop1,loop2);

	languageData->finishing = 0;
	loop_ticker2 = 0;
#endif

}

#ifdef _WINDOWS
extern int useScale2D;
#endif

void languageDraw(void)
{
#if PREVIEW_VERSION==1
	overlayPreviewOverlay();
#endif

	setCamera(languageData->lastFade*500*languageData->fadeDirection,0,-12000+(long)languageData->finishing*128,	languageData->lastFade * 500 * languageData->fadeDirection,0,0);
	languageTransformPoints();

#ifdef _WINDOWS
	useScale2D=0;
#endif
	languageDrawPolys();
#ifdef _WINDOWS
	useScale2D=1;
#endif

	if (gameTextLang < LANG_NUMLANGS+1)
		fontPrint(font,-fontExtentW(font,(TEXTSTR(TEXTSTR_OPTIONS_LANGUAGE_ENGLISH+gameTextLang)))/2,-105,TEXTSTR(TEXTSTR_OPTIONS_LANGUAGE_ENGLISH+gameTextLang),128,128,128);

	fontPrintCentred(font,0,90,TEXTSTR(TEXTSTR_OPTIONS_SELECT),128,128,128);
	overlaySpriteFlipped(langarrowspr, -232, -12, 0, 0x808080);
	overlaySprite(langarrowspr, 215, -12, 0, 0x808080);
}

void languageCycle()
{
	long loop1,loop2,temp;
	
	optionsDebouncedAnalogCycle();
	
	languageData->wind[0] += utilRandomInt(800)-100+rsin(languageData->frame*200)/15;
	languageData->wind[0] = languageData->wind[0]/2;
	for(loop1 = FLAGPOINTS*2-1; loop1 > 0; loop1 --)
		languageData->wind[loop1] = languageData->wind[loop1-1];

	languageData->crosswind[0] += utilRandomInt(900)+rsin(languageData->frame*170)/15;
	languageData->crosswind[0] = languageData->wind[0]/2;
	for(loop1 = FLAGPOINTS-1; loop1 > 0; loop1 --)
		languageData->crosswind[loop1] = languageData->crosswind[loop1-1];
	

	if (((padData.debounce[0] & PAD_LEFT) ||(stickleft==1)) && !languageData->lastFade && !languageData->finishing)
	{
		gameTextLang = (gameTextLang+(LANG_NUMLANGS+1-1)-1)%(LANG_NUMLANGS+1-1);
		languageData->lastFade = 1;
		languageData->fadeDirection = -1;
	}
	if ( ((padData.debounce[0] & PAD_RIGHT) || (stickright==1)) && !languageData->lastFade && !languageData->finishing)
	{
		gameTextLang = (gameTextLang+1)%(LANG_NUMLANGS+1-1);
		languageData->lastFade = 1;
		languageData->fadeDirection = 1;
	}

	if (languageData->lastFade) languageData->lastFade++;
	if (languageData->lastFade>16)
	{
		languageData->tileTexture = gameTextLang;
		languageData->lastFade=-16;
		for(loop1 = 0; loop1 < FLAGPOLYS; loop1 ++)
			for(loop2 = 0; loop2 < FLAGPOLYS; loop2 ++)
				calculateTileTexture(loop1,loop2);
	}

	for(loop1 = 0; loop1 < FLAGPOINTS; loop1 ++)
	{
		for(loop2 = 0; loop2 < FLAGPOINTS; loop2 ++)
		{
			if (loop1 == 0)
				languageData->accel[loop1][loop2] = (languageData->accel[loop1][loop2] + languageData->wind[loop2+loop1] + languageData->crosswind[loop1]) / 3;
			else
				languageData->accel[loop1][loop2] = (languageData->accel[loop1-1][loop2] + (languageData->wind[loop2+loop1]/2) + languageData->crosswind[loop1]) / 2;
			if (!(loop1 + languageData->frame)) languageData->accel[loop1][loop2] += utilRandomInt(128)-64;

			languageData->flagPoints[loop1][loop2].vz += languageData->accel[loop1][loop2];
			languageData->flagPoints[loop1][loop2].vz = (languageData->flagPoints[loop1][loop2].vz*9)/10;
			temp = (languageData->flagPoints[loop1][loop2].vz)/20;
			if (temp > 180) temp = 180;
			if (temp < 0) temp = 0;
			languageData->flagShade[loop1][loop2] = 255-temp;
		}
	}

	languageData->frame++;


	if(SwimCheatCycle())
	{
		DB("Going to the Development stuff\n");
		languageDestroy();
		startupFreeStart();
		menuStart();
	}



	if ((padData.debounce[0] & PAD_CROSS && loop_ticker2 > 25)	// ">20" is in case you were hammering "X" during bootup
		|| languageData->finishing) 
		languageData->finishing+=2;

	if (languageData->finishing > 64)
	{
		if (gameTextLang > LANG_NUMLANGS)
		gameTextLang = LANG_UK;
		languageDestroy();

// After selecting the language, drop through to the first memory card check
// (Which loads up options, and complains about present-but-full memory cards)
		cardPostLangStart();	//		startupStart();
	}
}

void languageDestroy(void)
{

//	if(imagePtr)	FREE(imagePtr);
	// free memory and stuff

	textureUnloadBank(languagebank);
	languagebank = NULL;

	textureUnloadBank(languageData->flagTextures);
	languageData->flagTextures = NULL;

	FREE(languageData);
	languageData = NULL;


	if(gameTextLang>=LANG_NUMLANGS) gameTextLang=LANG_UK;

	if(gameTextLang!=LANG_UK)
	{
		gameTextDestroy();
		sound_XA_PauseForLoading();

		gameTextInit("SHELL\\GAMETEXT.TXT", TEXTSTR_MAX, LANG_FILE_NUMLANGS, gameTextLang);		// 4 is number of langs, gameTextLang is one we want

		sound_XA_Resume(-1);
	}

	//gameTextDestroy();

	//*************************
	//gameTextLang=LANG_UK;		// Temporary - until language select screen is fixed for 
								// languages other than English
	//*************************

	//	gameTextInit(gameTextLang);

}

void languageDrawBackground(void)
{
	int i, j;

#ifndef _WINDOWS
	for(i=-256;i<256;i+=64)
		for(j=-127;j<120;j+=64)
			overlaySprite(plank, i, j, 1023, 0x808080);
#else
	for(i=-scrOffsetX;i<scrOffsetX;i+=64)
		for(j=-scrOffsetY;j<scrOffsetY;j+=64)
			overlaySprite(plank, i, j, 1023, 0x808080);
#endif

}

void SwimCheatReset()
{
	language_cheatmode = 0;
}

int SwimCheatCycle()
{
	int ang1;
	int ang2;

	if(ABS(padData.analogYS[0]) < 2000 && ABS(padData.analogXS[0]) < 2000)
	{
		ang1 = -1;
		SwimCheatReset();
	}
	else
	{
		ang1 = utilCalcAngle(padData.analogXS[0],padData.analogYS[0]) & 4095;
	}

	if(ABS(padData.analogY2S[0]) < 2000 && ABS(padData.analogX2S[0]) < 2000)
	{
		ang2 = -1;
		SwimCheatReset();
	}
	else
	{
		ang2 = utilCalcAngle(padData.analogX2S[0],padData.analogY2S[0]) & 4095;
	}

	//	DB("ang1=%d, ang2=%d\n",ang1,ang2);
	switch(language_cheatmode)
	{
		case 0:
			if(    ang1 > 1024-LANG_CHEAT_TOLERANCE && ang1 < 1024 + LANG_CHEAT_TOLERANCE
				&& ang2 > 3076-LANG_CHEAT_TOLERANCE && ang2 < 3076 + LANG_CHEAT_TOLERANCE
				)
			{
				DB("1\n");
				language_cheatmode++;
			}
			break;
		case 1:
			if(    ang1 > 2048-LANG_CHEAT_TOLERANCE && ang1 < 2048 + LANG_CHEAT_TOLERANCE
				&& ang2 > 2048-LANG_CHEAT_TOLERANCE && ang2 < 2048 + LANG_CHEAT_TOLERANCE
				)
			{
				DB("2\n");
				language_cheatmode++;
			}
			break;
		case 2:
			if(    ang1 > 3076-LANG_CHEAT_TOLERANCE && ang1 < 3076 + LANG_CHEAT_TOLERANCE
				&& ang2 > 1024-LANG_CHEAT_TOLERANCE && ang2 < 1024 + LANG_CHEAT_TOLERANCE
				)
			{
				DB("3\n");
				language_cheatmode++;
			}
			break;
		case 3:
			if(    (ang1 < LANG_CHEAT_TOLERANCE || ang1 > 4096 - LANG_CHEAT_TOLERANCE)
				&& (ang2 < LANG_CHEAT_TOLERANCE || ang2 > 4096 - LANG_CHEAT_TOLERANCE)
				)
			{
				DB("4\n");
				language_cheatmode++;
			}
			break;
		case 4:
			SwimCheatReset();
			return 1;
	}
	return 0;
}
