#include "glover.h"

// This deals with special stuff in carnival 1, ie fruit machine etc.

#define CA_DB
//#define CA_DB DB

#define JACKPOT_CROWN		0
#define JACKPOT_FROGGY		1
#define JACKPOT_QUESTION	2
#define JACKPOT_GARIBS		3

#define FRUITMACHINE_NOISE	SFX_GENERIC_BLEEP_1

#define TAG_FRUIT_HOLD1		11
#define TAG_FRUIT_HOLD2		113
#define TAG_FRUIT_HOLD3		89
#define TAG_FRUIT_GO		99

#define TAG_FRUIT_REEL1		116
#define TAG_FRUIT_REEL2		188
#define TAG_FRUIT_REEL3		168

#define TAG_FRUIT_BUT		151
#define TAG_DIBGAME_BUT		81
#define TAG_PINBALL_BUT		108

#define TAG_FRUIT_BLANK		174

#define TAG_FRUIT_BOVVA		67
#define TAG_FRUIT_GARIBS	2

#define TAG_ROCKETSLOPE1	133
#define TAG_ROCKETSLOPE2	25
#define TAG_ROCKETSLOPE3	57

#define TAG_HAMMER			39

#define TAG_MAGNET			110
#define TAG_MAGNET_ONOFF	161
#define TAG_MAGNET_LEFT		91
#define TAG_MAGNET_RIGHT	172

#define POINT_MAGNET_LEFT	5
#define POINT_MAGNET_RIGHT	6


struct
{
	short hold;
	short rotSpeed;
	short oldRotPos;
	short rotPos;
	short justPassedPoint;
}reel[3];

int tagRocketSlope[]={133,25,57};
int tagRocketSlopeCover[]={142,94,9};
int nRocketSwitches=0;


#define CA_DIB_HEIGHT (-580)

#define CA_DIB_FLYTIME (50)
#define CA_DIB_RANDTIME (127)
#define CA_DIB_DOWNTIME (90)
#define CA_DIB_YVEL (-7)

void carnival1Init(void)
{
	int r[3], i;

	// this is so rocket slopes start from no. 1 each time the level is played
	nRocketSwitches=0;

	for(i=0; i<3; i++)
		r[i]=0;

	// initialise fruit machine reels to 3 different symbols
	while((r[0]==r[1]) || (r[1]==r[2]) || (r[2]==r[0]))	// don't exit until the reels are all different
	{
		for(i=0; i<3; i++)
			r[i]=random(4);
	}

	for(i=0; i<3; i++)
		reel[i].rotPos=(r[i]*0x400)+0x200;
}

void carnival1Handler(void)
{
	DYNCOLLBOX *ptr;
	int i,j;
	int jackpot;
	DYNCOLLBOX *pMag;

	//static int calledBefore=0;
	static int justStopped=0; 

	if(gameCtrl.PauseActive)
		return;

	// wak-a-dibber
	{
		static unsigned char dib_tags[] = {126,109,82,13,115,122,70,95};
		for(i = 0; i < 8; i++)
		{
			ENEMYPOS *nme;

			nme = loadlndFindEnemy(dib_tags[i]);
			if(!(nme->flags & NMEFLAG_DEAD))
			{
				switch(nme->doing)
				{
				case 200:
					nme->ticker--;
					if(!nme->ticker)	// dibber goes "sproing" out of the ground
					{
						sfxPlayNME3D(globalFX, SFX_GE_SAMTEX_WALK,nme);

						nme->flags |= NMEFLAG_ACTIVE;
						nme->vel.vy = CA_DIB_YVEL << 12;
						nme->vel.vx = RANDOM256() - 127;	// spin
						nme->doing = 201;
						nme->pos.vy = CA_DIB_HEIGHT << 12;
						nme->ticker = CA_DIB_FLYTIME;
					}
					break;

				case 201:	// dibber hangs around for a while, bouncing
				case 202:
				case 203:
					nme->pos.vy += nme->vel.vy;
					nme->vel.vy += gravity;
					nme->ya = (nme->ya + nme->vel.vx) & 4095;

				case 204:

					if(nme->pos.vy > CA_DIB_HEIGHT << 12)
					{
						nme->pos.vy = CA_DIB_HEIGHT << 12;
						nme->vel.vy = -nme->vel.vy / 2;
						if(nme->doing < 204)
							nme->doing++;
					}

					nme->ticker--;

					if(!nme->ticker)	// dibber vanishes
					{
						nme->doing = -1;
						New_Debris(DEBRIS_DUST,&nme->pos,0x201810);

					}
					break;



				default:	// turn normal dibber behaviour off
					AddToQueue(&nme->anim,0,YES,NO,4096);	// dibs only have the one anim

					nme->doing = 200;
					nme->ticker = (RANDOM256() & CA_DIB_RANDTIME) + CA_DIB_DOWNTIME;
					nme->flags &= ~NMEFLAG_ACTIVE;
					break;
				}
			}
		}
	}

	// update spinny reels
	for(i=0; i<3; i++)
	{
		if(reel[i].hold==FALSE)
		{
			if(reel[i].rotSpeed>0)
			{
				int r0, r1;

				reel[i].oldRotPos=reel[i].rotPos;

				r0=reel[i].rotPos & 0x3ff;
				reel[i].rotPos+=reel[i].rotSpeed;
				r1=reel[i].rotPos & 0x3ff;

				if((r0<0x200) && (r1>=0x200)) // has reel passed a stop?
				{
					CA_DB("Make noise!\n");
					reel[i].justPassedPoint=TRUE;
				}
				else
				{
					reel[i].justPassedPoint=FALSE;
				}

				reel[i].rotPos&=0xfff;

				if(reel[i].rotSpeed<0x20)
				{
					for(j=0x200; j<=0xe00; j+=0x400)
					{
						if((reel[i].oldRotPos<j) && (reel[i].rotPos>=j))
						{
							justStopped=TRUE;
							reel[i].rotSpeed=0;
							reel[i].rotPos=j;
						}
					}
				}
				else
				{
					reel[i].rotSpeed--;
				}
			}
		}
	}

	if((reel[0].rotSpeed==0) && (reel[1].rotSpeed==0) && (reel[2].rotSpeed==0) && justStopped)
	{
		if((reel[0].rotPos==reel[1].rotPos) && (reel[1].rotPos==reel[2].rotPos))
		{
			VECTOR pos;

			jackpot=(reel[0].rotPos-0x200)/0x400;
			CA_DB("Jackpot is %d!\n", jackpot);

			// turn on switch whatever the jackpot ...

			puzzleSetExistence(TAG_FRUIT_BUT, 1);
			puzzleSetExistence(TAG_FRUIT_BLANK, 0);

			if((jackpot==JACKPOT_CROWN) || (jackpot==JACKPOT_FROGGY))
			{
				DYNCOLLBOX *pBox;

				loadlndFindPlatform(TAG_FRUIT_BUT, NULL, &pBox);
				COPYVECTOR(&pos, &(pBox->pPlatDef->points[0].pos));
				pos.vy-=0x2000; //move it up a bit
			}

			switch(jackpot)
			{
			case JACKPOT_CROWN:
				effectsStartOverlay(20, 0x0000ff);

				ca_pickup_nme[0]->flags |= (NMEFLAG_ENABLED + NMEFLAG_ACTIVE);
				pos.vy -= 30 << 12;
				pos.vx -= 30 << 12;
				ca_pickup_nme[0]->pos = pos;

//				puzzleCreatePickup(0, &pos);
				break;
			case JACKPOT_FROGGY:
				effectsStartOverlay(20, 0x00ff00);
				ca_pickup_nme[1]->flags |= (NMEFLAG_ENABLED + NMEFLAG_ACTIVE);
				pos.vy -= 30 << 12;
				pos.vx += 30 << 12;
				ca_pickup_nme[1]->pos = pos;
//				puzzleCreatePickup(0, &pos);
				break;

			case JACKPOT_QUESTION:
				puzzleSetExistence(TAG_FRUIT_BOVVA, 1);
				break;
			case JACKPOT_GARIBS:
				puzzleSetExistence(TAG_FRUIT_GARIBS, 1);
			}
		}
	}

	// find pointer to magnet
	loadlndFindPlatform(TAG_MAGNET, NULL, &pMag);
	ASSERT(pMag);

	if(pMag->magnet.movingToMiddle)
	{
		CA_DB("Moving to middle ...\n");
		if(VectorMoveTo(&pMag->pos, &(pMag->pPlatDef->points[4].pos),  8192))
		{
			CA_DB("Now at middle\n");
			pMag->move.point=4;
			pMag->magnet.movingToMiddle=0;
			puzzleStartMove(TAG_MAGNET, 4,0); // move 'forever'
		}
	}
	
	if(puzzleAtPoint(pMag, 1))
	{
		pMag->magnet.active=1;
	}

	for(ptr = dyncollList.head.next; ptr != &dyncollList.head; ptr = ptr->next)
	{
		switch(ptr->pPlatDef->head.tag)
		{
		case TAG_FRUIT_REEL1:
			ptr->spin.progress=reel[0].rotPos;
			if(reel[0].justPassedPoint)
			{
				sfxSetSamplePitch(globalFX, FRUITMACHINE_NOISE, DEFAULT_PITCH-0x40);
				sfxPlay3D(globalFX, FRUITMACHINE_NOISE, &ptr->pos);
				sfxSetSamplePitch(globalFX, FRUITMACHINE_NOISE, DEFAULT_PITCH);

				reel[0].justPassedPoint=FALSE;
			}
			break;
		case TAG_FRUIT_REEL2:
			ptr->spin.progress=reel[1].rotPos;
			if(reel[1].justPassedPoint)
			{
				sfxSetSamplePitch(globalFX, FRUITMACHINE_NOISE, DEFAULT_PITCH);
				sfxPlay3D(globalFX, FRUITMACHINE_NOISE, &ptr->pos);
				reel[1].justPassedPoint=FALSE;
			}
			break;
		case TAG_FRUIT_REEL3:
			ptr->spin.progress=reel[2].rotPos;
			if(reel[2].justPassedPoint)
			{
				sfxSetSamplePitch(globalFX, FRUITMACHINE_NOISE, DEFAULT_PITCH+0x40);
				sfxPlay3D(globalFX, FRUITMACHINE_NOISE, &ptr->pos);
				sfxSetSamplePitch(globalFX, FRUITMACHINE_NOISE, DEFAULT_PITCH);

				reel[2].justPassedPoint=FALSE;
			}
			break;

		case TAG_FRUIT_HOLD1:
			if(reel[0].rotSpeed==0)
				reel[0].hold=CompareVectors(&(ptr->pos), &(ptr->pPlatDef->points[1].pos));
			break;
		case TAG_FRUIT_HOLD2:
			if(reel[1].rotSpeed==0)
				reel[1].hold=CompareVectors(&(ptr->pos), &(ptr->pPlatDef->points[1].pos));
			break;
		case TAG_FRUIT_HOLD3:
			if(reel[2].rotSpeed==0)
				reel[2].hold=CompareVectors(&(ptr->pos), &(ptr->pPlatDef->points[1].pos));
			break;

		case TAG_FRUIT_GO:
			// Start reels spinning really fast :)
			if(puzzleJustAtPoint(ptr, 1))
			{
				CA_DB("Spinning reels\n");

				if((reel[0].rotSpeed==0) && (reel[1].rotSpeed==0) && (reel[2].rotSpeed==0))
				{
					for(i=0; i<3; i++)
					{
						if(reel[i].hold==FALSE)
							reel[i].rotSpeed=192+random(64);
					}
				}
			}

			break;

		case TAG_FRUIT_BUT:
		case TAG_DIBGAME_BUT:
		case TAG_PINBALL_BUT:
			//if(ptr->move.jap && (ptr->move.point==1))
			if(puzzleJustAtPoint(ptr, 1))
			{
				//CA_DB("nRocketSwitches=%d\n", nRocketSwitches);
				puzzleSetExistence(tagRocketSlope[nRocketSwitches], 1);
				puzzleSetExistence(tagRocketSlopeCover[nRocketSwitches], 0);
				puzzleStartMove(tagRocketSlope[nRocketSwitches], 6,0);
				nRocketSwitches++;
			}
			break;

		case TAG_HAMMER:
			if(puzzleJustAtPoint(ptr, 1))
			{
				if(handpower_type != SPELL_HERCULES)
					ptr->move.point=3; // force it to last point so hammer never reaches the top

				puzzleStartMove(TAG_HAMMER, 4,0); // move 'forever'
			}
			else
			{
				if(puzzleJustAtPoint(ptr, 2))
				{// To get here we must have hercules!
					CA_DB("You have won a prize!\n");
				}
			}

			break;

		case TAG_MAGNET:

			//CA_DB("Magnet speed = %d\n", ptr->move.speed);

			if(puzzleJustAtPoint(ptr, 4))
			{
				CA_DB("Magnet is at the end\n");
				ptr->magnet.atEnd=TRUE;
			}
			break;

		case TAG_MAGNET_ONOFF:
			if(puzzleJustAtPoint(ptr, 1)) // magnet button has just been pushed
			{
				CA_DB("Magnet button pushed\n");


				// stinky bodge. This stops the last 2 points being cycled through
				pMag->pPlatDef->head.n_points=5;

				if(pMag->magnet.atEnd)
				{
					pMag->magnet.atEnd=FALSE;
					pMag->magnet.active=0;

					// we need to cause the magnet to go to the middle, before we move it back.
					pMag->magnet.movingToMiddle=TRUE;

					CA_DB("Moving magnet to middle ...\n");
				}
				else
				{
					puzzleStartMove(TAG_MAGNET, 4, 0);
				}

				CA_DB("Magnet status = %d\n", pMag->magnet.active);
			}

			break;

		case TAG_MAGNET_LEFT:
			if(gloveColl.nHitPlats && (gloveColl.hitPlats[0].pPlatform==ptr) && pMag->magnet.atEnd)
			{// glove is touching left button
				CA_DB("Magnet left ...\n");
				VectorMoveTo(&pMag->pos, &(pMag->pPlatDef->points[POINT_MAGNET_LEFT].pos),  4096);
			}
			break;

		case TAG_MAGNET_RIGHT:
			if(gloveColl.nHitPlats && (gloveColl.hitPlats[0].pPlatform==ptr) && pMag->magnet.atEnd)
			{// glove is touching right button
				CA_DB("Magnet right ...\n");
				VectorMoveTo(&pMag->pos, &(pMag->pPlatDef->points[POINT_MAGNET_RIGHT].pos),  4096);
			}
			break;
		}
	}

	//sfxSetSamplePitch(bank, sfx, DEFAULT_PITCH);
	//sfxSetSampleVolume(bank, sfx,DEFAULT_VOLUME);

	justStopped=0;
}
