#pragma On(Align_all_labels)
#pragma On(Align_labels)

#include <stdio.h>
#include <limits.h>

#include <concorde.h>
#include <tomahawk.h>

#include <airforce.h>


static int AL_3D_Crash_Mountain(int *str,int *spo);
static int AL_3D_Crash_Building(int *str,int *spo);
static int AL_3D_Crash_Polygon_InOrOut(int *ptr,int cx,int cz);
static int AL_3D_Crash_Polygon(int *str,int *spo);
static int AL_3D_Crash_Bridge(int *str,int *spo);


int *AL_Crash(LAXIS *lax,int *pos)
{
	int *str,lpo[3],spo[3];

	switch((*lax).unit)
	{
	case UNI_METER:
		lpo[0]=pos[0]/100-(*lax).wcx;
		lpo[1]=pos[1]/100;
		lpo[2]=pos[2]/100-(*lax).wcz;
		break;
	case UNI_CENTI:
		lpo[0]=pos[0]-(*lax).wcx;
		lpo[1]=pos[1];
		lpo[2]=pos[2]-(*lax).wcz;
		break;
	}

	if(lpo[1]>(*lax).hight)return NULL;

	RotHq(&lpo[0],&lpo[2],-(*lax).wdir);
	if(lpo[0]<(*lax).xs || (*lax).xl<lpo[0] ||
	   lpo[2]<(*lax).zs || (*lax).zl<lpo[2])return NULL;

	spo[1]=lpo[1];
	for(str=(*lax).str; *str!=STR_EOF; str+=AL_Sizeof_Str(str))
	{
		if(lpo[0]<str[1] || str[3]<lpo[0] ||
		   lpo[2]<str[2] || str[4]<lpo[2])continue;

		spo[0]=lpo[0]-str[5];
		spo[2]=lpo[2]-str[7];
		RotHq(&spo[0],&spo[2],-str[8]);

		switch(*str)
		{
		case STR_MOUNTAIN:
			if(spo[1]>str[HEAD_STR+5])continue;
			if(AL_3D_Crash_Mountain(str,spo))return str;
			break;
		case STR_BUILDING:
			if(spo[1]>str[HEAD_STR+7])continue;
			if(AL_3D_Crash_Building(str,spo))return str;
			break;
		case STR_POLYGON:
			if(spo[1]>str[HEAD_STR+3])continue;
			if(AL_3D_Crash_Polygon(str,spo))return str;
			break;
		case STR_BRIDGE:
			if(AL_3D_Crash_Bridge(str,spo))return str;
			break;
		case STR_RUNWAY:
		case STR_HAZARD:
			if(spo[1]<=0)return str;
			break;
		}
	}
	return NULL;
}



static int AL_3D_Crash_Mountain(int *str,int *spo)
{
	int lx,lz;
	str+=HEAD_STR;
	lx=str[4];
	lz=str[5];

	if(spo[1]>lx-spo[0] || spo[1]>lx+spo[0])return 0;
	if(spo[1]>lz-spo[2] || spo[1]>lz+spo[2])return 0;
	return 1;
}

static int AL_3D_Crash_Building(int *str,int *spo)
{
	int lx,lz;
	str+=HEAD_STR;
	lx=str[5];
	lz=str[6];
	if(-lx<spo[0] && spo[0]<lx && -lz<spo[2] && spo[2]<lz)return 1;
	return 0;
}


static int AL_3D_Crash_Polygon_InOrOut(int *ptr,int cx,int cz)
{
	int i,x1,z1,x2,z2,lvz,vz,btw,cpx,ctr;
	extern int AL_Crash_Polygon_Linear(int,int,int,int,int);

	ctr=0;
	x1=ptr[*ptr*2-3];
	z1=ptr[*ptr*2-2];
	x2=ptr[*ptr*2-1];
	z2=ptr[*ptr*2  ];
	lvz=z2-z1;
	for(i=0; i<*ptr; i++)
	{
		x1=x2; z1=z2; x2=ptr[1+i*2]; z2=ptr[2+i*2]; vz=z2-z1;
		if     (vz==0)continue;
		else if(vz> 0)btw=(z1<cz && cz<=z2);
		else if(vz< 0)btw=(z2<cz && cz<=z1);
		if(vz*lvz<0)btw=(btw||(z1==cz));
		lvz=vz;
		if(btw==0)continue;
		cpx=AL_Crash_Polygon_Linear(z1,x1,z2,x2,cz);
		/*  (x2-x1)*(cz-z1)/(z2-z1)+x1;  */
		if(cpx<cx)ctr++;
	}
	if(ctr%2==0)return 0; else return 1;
}

static int AL_3D_Crash_Polygon(int *str,int *spo)
{
	return AL_3D_Crash_Polygon_InOrOut(str+HEAD_STR+4,spo[0],spo[2]);
}

static int AL_3D_Crash_Bridge(int *str,int *spo)
{
	int lx,lz;
	str+=HEAD_STR;
	lx=str[2];
	lz=str[3];
	if(-lx<spo[0] && spo[0]<lx && -lz<spo[2] && spo[2]<lz)return 1;
	return 0;
}
