
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "core.h"

#define ERRORON

int stacki[8];
float stackf[8];
int ptri=0;
int ptrf=0;

int sintab[360];
int costab[360];

float cam[3];
float look[3];

float timer;

void GenSINCOS()
{
	for (int i=0; i<360; i++)
	{
		sintab[i]=sin(i*3.14159265/180)*32768;
		costab[i]=cos(i*3.14159265/180)*32768;
	}
}

void Error(int errorcode)
{
#ifdef ERRORON
	printf("ERROR! %s\n",errortable[errorcode]);
	//add error file appending later.
#endif
}

void pushf(float num)
{
	stackf[ptrf]=num;
	if (ptrf+1<8) ptrf++;
}

void pushi(int num)
{
	stacki[ptri]=num;
	if (ptri+1<8) ptri++;
}

void popi(int *num)
{
	*num=stacki[ptri];
	if (ptri-1>=0) ptri--;
}

void popf(float *num)
{
	*num=stackf[ptrf];
	if (ptrf-1>=0) ptrf--;
}


float frand()
{
	return ((float)(((float)rand())/32768)-0.5)*2;
}

float f2rand()
{
	return (float)(((float)rand())/32768);
}

int i3rand(int range)
{
	return rand()%range;
}

void fclip(float lo,float hi,float *value)
{
	if (*value>hi) { *value=hi; return; }
	if (*value<lo) { *value=lo; return; }
}


void iclip(int lo,int hi,int *value)
{
	if (*value>hi) { *value=hi; return; }
	if (*value<lo) { *value=lo; return; }
}

void fwrap(float lo,float hi,float *value)
{
	if (*value>hi) { *value=lo; return; }
	if (*value<lo) { *value=hi; return; }
}


void iwrap(int lo,int hi,int *value)
{
	if (*value>hi) { *value=lo; return; }
	if (*value<lo) { *value=hi; return; }
}

int sqri(int num)
{
	return num*num;
}

float sqrf(float num)
{
	return num*num;
}

int cubei(int num)
{
	return num*num*num;
}

float cubef(float num)
{
	return num*num*num;
}

int biggesti(int num1,int num2)
{
	if (num1>num2) return num1;
	else return num2;
}

float biggestf(float num1,float num2)
{
	if (num1>num2) return num1;
	else return num2;
}

int smallesti(int num1,int num2)
{
	if (num1<num2) return num1;
	else return num2;
}

float smallestf(float num1,float num2)
{
	if (num1<num2) return num1;
	else return num2;
}

float length3d(float x1,float y1,float z1,float x2,float y2,float z2)
{
	return sqrt( sqrf(x1-x2)+sqrf(y1-y2)+sqrf(z1-z2) );
}

float length2d(float x1,float y1,float x2,float y2)
{
	return sqrt( sqrf(x1-x2)+sqrf(y1-y2) );
}

void rotate3d(float *x,float *y,float *z,float xdeg,float ydeg,float zdeg)
{
	float a,b,c;
	a=*x;
	b=*y;
	c=*z;

	//xdeg*=RAD;
	//ydeg*=RAD;
	//zdeg*=RAD;
/*X Axis:
 New_y = cos(Radians)*OldY - sin(Radians)*OldZ
 New_z = sin(Radians)*OldY + cos(Radians)*OldZ
 OldY = New_y
 OldZ = New_z

 Y Axis:
 New_x = cos(Radians)*OldX - sin(Radians)*OldZ
 New_z = sin(Radians)*OldX + cos(Radians)*OldZ
 OldX = New_x
 OldZ = New_z

 Z Axis(2D Rotation):
 New_x = cos(Radians)*OldX - sin(Radians)*OldY
 New_y = sin(Radians)*OldX + cos(Radians)*OldY
 OldY = New_y
 OldX = New_x

 Radians is the Radians of rotation.
*/
	//rotate about X-AXIS
	*y=b*cos(xdeg) + c*sin(xdeg);
	*z=c*cos(xdeg) - b*sin(xdeg);
	b=*y;
	c=*z;

	//rotate about Y-AXIS
	*x=a*cos(ydeg) - c*sin(ydeg);
	*z=c*cos(ydeg) + a*sin(ydeg);
	a=*x;
	c=*z;

	//rotate about Z-AXIS
	*x=a*cos(zdeg) + b*sin(zdeg);
	*y=b*cos(zdeg) - a*sin(zdeg);
}

//opens files doing errorchecking
FILE *FileOpen(char *filename)
{
	FILE *fh0;

	printf("Reading \"%s\":\n",filename);
	//check filename valid
	if ((!filename) || (strlen(filename)<1)) { Error(ERROR_FINVFN); return 0; }
	fh0=fopen(filename,"rb");
	//check file exists
	if (!fh0) { Error(ERROR_FNOTFOUND); return 0; }
	//yes it does
	return fh0;
}


//closes files
void FileClose(FILE *fh0)
{
	//close file, return ok
	int l=ftell(fh0);
	fseek(fh0,0,SEEK_END);
	int l2=ftell(fh0);
	fclose(fh0);
	printf("OK! (%i/%i bytes)\n\n",l,l2);
}



struct
{
	//blending
	bool blend;
	int blsrc,bldest;

	//lighting
	bool lights;

	//depth
	bool depthcheck;

} GLState;


void SaveGLState(int state)
{
	if (state==GLSTATE_BLEND)
	{
		GLState.blend=glIsEnabled(GL_BLEND);
		glGetIntegerv(GL_BLEND_SRC,&GLState.blsrc);
		glGetIntegerv(GL_BLEND_DST,&GLState.bldest);
	}
	if (state==GLSTATE_LIGHTS)
	{
		GLState.lights=glIsEnabled(GL_LIGHTING);
	}
	if (state==GLSTATE_DEPTH)
	{
		GLState.depthcheck=glIsEnabled(GL_DEPTH_TEST);
	}
}


void RestoreGLState(int state)
{
	if (state==GLSTATE_BLEND)
	{
		if (GLState.blend) glEnable(GL_BLEND);
			else glDisable(GL_BLEND);
		glBlendFunc(GLState.blsrc,GLState.bldest);
	}
	if (state==GLSTATE_LIGHTS)
	{
		if (GLState.lights) glEnable(GL_LIGHTING);
			else glDisable(GL_LIGHTING);
	}
	if (state==GLSTATE_DEPTH)
	{
		if (GLState.depthcheck) glEnable(GL_DEPTH_TEST);
			else glDisable(GL_DEPTH_TEST);
	}
}
//glPushAttrib( GL_ALL_ATTRIB_BITS );
//glPopAttrib();


void Synk(int time,int time2)
{

}

void TimerReset()
{
	//float curtime;
	timer=((float)clock()*10)/(float)CLOCKS_PER_SEC;
}

float TimeElapsed()			//in seconds
{
	float time;
	time=((float)clock()*10)/(float)CLOCKS_PER_SEC;
	return time-timer;
}