#include "glover.h"

LIGHTNINGLIST lightningList;

int drawFrame=0;

void lightningInitialise(void)
{
	lightningList.head.next = lightningList.head.prev = &lightningList.head;
	lightningList.numEntries = 0;
}

// Checks integrity of lightning linked list
void lightningVerify(void)
{
	LIGHTNING_DEFSTR *ptr;
	int c=0;

	for(ptr = lightningList.head.next;ptr != &lightningList.head;ptr = ptr->next)
	{
		ASSERT(ptr);
		c++;
	}

	ASSERT(c==lightningList.numEntries);
}

void lightningClearUpMessAfterwards(void)
{
	LIGHTNING_DEFSTR *ptr;

	lightningVerify();
	
	for(ptr = lightningList.head.next; ptr != &lightningList.head; ptr = ptr->next)
	{
		ptr->prev->next = ptr->next;
		ptr->next->prev = ptr->prev;
		lightningList.numEntries--;

		FREE(ptr);
	}

	ASSERT(lightningList.numEntries==0);
}

LIGHTNING_DEFSTR *lightningCreate(void)
{
	LIGHTNING_DEFSTR *ptr;
	LIGHTNING_DEFSTR *pWind=MALLOC(sizeof(LIGHTNING_DEFSTR), "Wind");

	lightningVerify();

	ptr=lightningList.head.next;

	pWind->next = ptr;
	pWind->prev = ptr->prev;
	ptr->prev->next = pWind;
	ptr->prev = pWind;
	lightningList.numEntries++;

	return pWind;
}

int lightningIsModelInRange(VECTOR *pPos, int radius)
{
	LIGHTNING_DEFSTR *ptr;
	DYNCOLLBOX *pPlat1, *pPlat2;

	SVECTOR *v1, *v2;
	VECTOR a,b;
	int d,e,f;
	int dp1,dp2;
	VECTOR p1, p2;
	VECTOR pos;
	int calc;

	// PLEASE NOTE: If this ASSERT fails, it means that lightningDrawAll() has not been called this frame,
	// before this function. It needs to be.
	ASSERT(drawFrame==frame);

	pos.vx=pPos->vx/4096;
	pos.vy=pPos->vy/4096;
	pos.vz=pPos->vz/4096;

	for(ptr = lightningList.head.next; ptr != &lightningList.head; ptr = ptr->next)
	{
		ASSERT(ptr);

		if(!ptr->active)
			continue;

		v1=ptr->calcPos;
		v2=ptr->calcPos+1;

		// work out whether lightning has hurt the ball or glove ...

		a.vx=v2->vx-v1->vx;
		a.vy=v2->vy-v1->vy;
		a.vz=v2->vz-v1->vz;

		SUBVECTOR(&p1, v1, &pos);
		SUBVECTOR(&p2, v2, &pos);

		dp1=DotProduct(&a, &p1);
		dp2=DotProduct(&a, &p2);

		b.vx=(pos.vx)-v1->vx;
		b.vy=(pos.vy)-v1->vy;
		b.vz=(pos.vz)-v1->vz;

		MakeUnit(&a);
		
		e=DotProduct(&a, &b);
		f=Magnitude(&b);
		//d=fast_sqrt((f*f)-(e*e))>>4;
		calc=(f*f)-(e*e);
		FASTSQRT(d,calc);
		d=d>>4;
		//DB("v1=%d,%d,%d v2=%d,%d,%d\n", v1.vx, v1.vy, v1.vz, v2.vx, v2.vy, v2.vz);
		//DB("You are within %d thingies of lightning\n", d);

		if((d<=(radius*2)) && (dp1<0) && (dp2>0))
		{
			//return(FALSE);
			//DB("You are up shit street\n");
			return(TRUE);
		}
	}

	return(FALSE);
}

void lightningDrawAll(void) // This MUST be called BEFORE lightningIsModelInRange()
{
	LIGHTNING_DEFSTR *ptr;
	DYNCOLLBOX *pPlat[2];
	SVECTOR v[2];
	
	drawFrame=frame;

	//DB("lightningDrawAll ...\n");
	for(ptr = lightningList.head.next; ptr != &lightningList.head; ptr = ptr->next)
	{
		int i;

		ASSERT(ptr);

		ptr->active=TRUE;

		for(i=0; i<2; i++)
		{
			loadlndFindPlatform(ptr->pTag[i], NULL, pPlat+i);
			ASSERT(pPlat[i]);

			if(!pPlat[i]->active)
				ptr->active=FALSE;

			v[i].vx=pPlat[i]->cumPos.vx/4096;
			v[i].vy=pPlat[i]->cumPos.vy/4096;
			v[i].vz=pPlat[i]->cumPos.vz/4096;
			
			*(ULONG *)&(ptr->calcPos[i].vx)=*(ULONG *)(v+i);
			ptr->calcPos[i].vz=v[i].vz;
		}

		if(!ptr->active)
		{
			continue;
		}

		if(!(activeframe & 7) && world == FORTRESS)
		{
			if(!(activeframe & 8))
				sfxPlay3D(levelFX,SFX_FRANKIE_ATTACK_LOOPED,&pPlat[0]->cumPos);
			else
				sfxPlay3D(levelFX,SFX_FRANKIE_ATTACK_LOOPED,&pPlat[1]->cumPos);
		}
//ULONG sfxPlay3D(int vab,int sampleNum, VECTOR *position);


		gte_SetTransMatrix(&GsWSMATRIX);
		gte_SetRotMatrix(&GsWSMATRIX);

		effectsDrawLightningStrand(v,v+1, *(ULONG *)&(ptr->colour));


	}
}

