#include <default.h>
#include <math.h>
#include <awl.h>
#include <efx2d.h>
#include <aw3d.h>
#include <awm.h>
#include <bass.h>
#include "part.h"

/*[ 3D ]*****************************************************/

DWORD LlumX=160;
bool CheatEnabled1 = false;
bool CheatEnabled2 = false;

typedef struct
{
  int x, y, z;
} Punto3D;

/*[ NINOT ]**************************************************/

typedef int TNINOT [15][2];

typedef struct {
  int   status;
  int   life;
  int   x, y;
  float time;
  float timep;
  Punto3D box[2];
  TNINOT  punts;
} Player;

Player Player1;
Player Player2;

const TNINOT NINOT_Linies={
  {0,1},
  {1,2},
  {2,3},
  {3,4},
  {4,0},
  {3,5},
  {5,6},
  {6,7},
  {5,8},
  {8,9},
  {5,10},
  {10,11},
  {10,12},
  {11,13},
  {12,14}
};

#include "ninot.h"

int Player1Status;
int Player2Status;

void RenderNinot (int x,int y,int status,float pos,DWORD col,bool reverse)
{       
  TNINOT in;
  TNINOT in2;                                
  switch (status)
  {  
    case 0:   
        memcpy (in,NINOT_Quiet,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 1: 
        memcpy (in,NINOT_Quiet,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos1,sizeof(NINOT_Quiet));
      break;
    case 2: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Punch,sizeof(NINOT_Quiet));
      break;
    case 3: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Kick,sizeof(NINOT_Quiet));
      break;
    case 4:
        memcpy (in,NINOT_Kick,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Punch,sizeof(NINOT_Quiet));
      break;
    case 5:
        memcpy (in,NINOT_Punch,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 6:
        memcpy (in,NINOT_Kick,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 7: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos2,sizeof(NINOT_Quiet));
      break;
    case 8: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos4,sizeof(NINOT_Quiet));
      break;
  }
  for (int i=0; i<15; i++)
  {
    int x11 = in[NINOT_Linies[i][0]][0];
    int x12 = in2[NINOT_Linies[i][0]][0];
    int y11 = in[NINOT_Linies[i][0]][1];
    int y12 = in2[NINOT_Linies[i][0]][1];
    int x21 = in[NINOT_Linies[i][1]][0];
    int x22 = in2[NINOT_Linies[i][1]][0];
    int y21 = in[NINOT_Linies[i][1]][1];
    int y22 = in2[NINOT_Linies[i][1]][1];

    float x1 = x11+((float)x12-x11)*pos;
    float y1 = y11+((float)y12-y11)*pos;
    float x2 = x21+((float)x22-x21)*pos;
    float y2 = y21+((float)y22-y21)*pos;
    y1 = (y1-7) * 5; y2 = (y2-7) * 5;
    if (reverse)
    {
      x1 = (8-x1) * 5; x2 = (8-x2) * 5;
      Player1.punts[i][0] = x1;
    } else {
      x1 = (x1-6) * 5; x2 = (x2 - 6) * 5;
      Player2.punts[i][0] = x2;
    }        
    x1+=x; x2+=x;
    y1+=y; y2+=y;
    // Sombra //
    float xx1, xx2;
    float yy1, yy2;
    yy1 = ((y1-165) * 0.6) + 165;
    yy2 = ((y2-165) * 0.6) + 165;

    if (reverse)
    {
      xx1 = x1+(y1-165)*(0.03f*(LlumX-x1)); 
      xx2 = x2+(y2-165)*(0.03f*(LlumX-x2));
    } else {
      xx1 = x1-(y1-165)*(0.03f*(x1-LlumX));
      xx2 = x2-(y2-165)*(0.03f*(x2-LlumX));
    }        
    AALine (xx1,yy1, xx2,yy2, 0x00000000);
    AALine (x1,y1, x2,y2, col);
		if ((i==7) || (i==9))
			PutPartRGB (GBL_Bits,(DWORD *)Sang->bits,x2,y2,12);
  }
}

void RenderNinot2 (int x,int y,int status,float pos,DWORD col,bool reverse)
{       
  TNINOT in;
  TNINOT in2;                                
  switch (status)
  {  
    case 0:   
        memcpy (in,NINOT_Quiet,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 1: 
        memcpy (in,NINOT_Quiet,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos1,sizeof(NINOT_Quiet));
      break;
    case 2: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Punch,sizeof(NINOT_Quiet));
      break;
    case 3: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Kick,sizeof(NINOT_Quiet));
      break;
    case 4:
        memcpy (in,NINOT_Kick,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Punch,sizeof(NINOT_Quiet));
      break;
    case 5:
        memcpy (in,NINOT_Punch,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 6:
        memcpy (in,NINOT_Kick,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet,sizeof(NINOT_Quiet));
      break;
    case 7: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos2,sizeof(NINOT_Quiet));
      break;
    case 8: 
        memcpy (in,NINOT_Pos1,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos4,sizeof(NINOT_Quiet));
      break;
    case 10: 
        memcpy (in,NINOT_Pos10,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Pos11,sizeof(NINOT_Quiet));
      break;
    case 11: 
        memcpy (in,NINOT_Quiet,sizeof(NINOT_Quiet));
        memcpy (in2,NINOT_Quiet2,sizeof(NINOT_Quiet));
      break;
  }
  for (int i=0; i<15; i++)
  {
    int x11 = in[NINOT_Linies[i][0]][0];
    int x12 = in2[NINOT_Linies[i][0]][0];
    int y11 = in[NINOT_Linies[i][0]][1];
    int y12 = in2[NINOT_Linies[i][0]][1];
    int x21 = in[NINOT_Linies[i][1]][0];
    int x22 = in2[NINOT_Linies[i][1]][0];
    int y21 = in[NINOT_Linies[i][1]][1];
    int y22 = in2[NINOT_Linies[i][1]][1];

    float x1 = x11+((float)x12-x11)*pos;
    float y1 = y11+((float)y12-y11)*pos;
    float x2 = x21+((float)x22-x21)*pos;
    float y2 = y21+((float)y22-y21)*pos;
    y1 = (y1-7) * 5; y2 = (y2-7) * 5;
    if (reverse)
    {
      x1 = (8-x1) * 5; x2 = (8-x2) * 5;
      Player1.punts[i][0] = x1;
    } else {
      x1 = (x1-6) * 5; x2 = (x2 - 6) * 5;
      Player2.punts[i][0] = x2;
    }        
    x1+=x; x2+=x;
    y1+=y; y2+=y;
    AALine (x1,y1, x2,y2, col);
		if ((i==7) || (i==9))
			PutPartRGB (GBL_Bits,(DWORD *)Sang->bits,x2,y2,12);
  }
}

/*[ ESTATS ]*************************************************/

#define STAND  1
#define POS1   2
#define PUNCH  3
#define KICK   4

#define PLAYER1_HIT  1
#define PLAYER2_HIT  2

/*[ PLAYERS ]************************************************/

TImage *GetSome[3];

/*[ INICIALITZA PLAYERS ]************************************/

void PlayersInit (void)
{
  Player1.x = 80;
  Player1.y = 120;
  Player2.x = 320-80;
  Player2.y = 120;
}

/*[ CREA CAIXES DE COLISIO ]*********************************/

void PlayersCreateBox (void)
{
  int i;
  int minx, miny;
  int maxx, maxy;

  minx = miny =  9999999999;
  maxx = maxy = -9999999999;
  for (i = 0; i < 15; i++)
  {
    if (Player1.punts[i][0] < minx) minx = Player1.punts[i][0];
    if (Player1.punts[i][0] > maxx) maxx = Player1.punts[i][0];
  }
  Player1.box[0].x = minx;
  Player1.box[1].x = maxx;

  minx = miny =  9999999999;
  maxx = maxy = -9999999999;
  for (i = 0; i < 15; i++)
  {
    if (Player2.punts[i][0] < minx) minx = Player2.punts[i][0];
    if (Player2.punts[i][0] > maxx) maxx = Player2.punts[i][0];
  }
  Player2.box[0].x = minx;
  Player2.box[1].x = maxx;
}

/*[ COMPROVA COLISIO ENTRE CAIXES ]**********/

int Colisio (void)
{
  if ((Player1.x+50) > (Player2.x-7)) return 1;
	return 0;
}

/*[ COMPROVA COLISIONS DE COPS ]*************/

int Colisions (void)
{
  /*[ EL PLAYER 1 PEGA ]***********************/
  if (Player1.status == 2 || Player1.status == 3)
  {
    if (Colisio ()) return PLAYER1_HIT; 
  }                                    
  /*[ EL PLAYER 2 PEGA ]***********************/
  if (Player2.status == 2 || Player2.status == 3)
  {
    if (Colisio ()) return PLAYER2_HIT; 
  }
	return 0;
}                                                             

/*[ DIBUIXA PLAYERS ]****************************************/

void PlayersDraw (void)
{
	DWORD col = 0xff;
	if (CheatEnabled1) RGB_Set (col,rand()%256,rand()%256,rand()%256);
	RenderNinot (Player1.x,Player1.y,Player1.status,Player1.time,col,1);

	col = 0xff0000;
	if (CheatEnabled2) RGB_Set (col,rand()%256,rand()%256,rand()%256);
	RenderNinot (Player2.x,Player2.y,Player2.status,Player2.time,col,0);
}

/*[ MAIN ]***************************************************/
/*[ MAIN ]***************************************************/
/*[ MAIN ]***************************************************/
/*[ MAIN ]***************************************************/

TImage * Image;
TImage * Image2;
TImage * Flare;
TImage * End;

bool GetSomeAra=false;
int GetSomeQuin;
int GetSomeCount=0;

void main (int argc, char * argv[])
{
  if (!DEFAULT_Init ()) return;

  char music[255]="fast.mp3";
  if (argc>1) strcpy (music,argv[1]);

  Image = IMAGE_Load ("fons.tga",32);
  IMAGE_FlipV (Image);

  Image2 = IMAGE_Load ("fons3.tga",32);
  IMAGE_FlipV (Image2);

  Flare = IMAGE_Load ("flare.tga",32);
  IMAGE_FlipV (Flare);
  
  End = IMAGE_Load ("End.tga",32);
  IMAGE_FlipV (End);

	Sang = IMAGE_Load ("sang.tga",32);
  
  GetSome[0] = IMAGE_Load ("te1.gif",8);
  GetSome[1] = IMAGE_Load ("te2.gif",8);
  GetSome[2] = IMAGE_Load ("te3.gif",8);    

  if (!MUSIC_Load (music)) return;
  MUSIC_Play ();
  
/*[ INIT JOC ]***********************************************/  

  PlayersInit ();

	float a=0;
  while (!Keys[VK_SPACE])
  {
    MISC_MemCpy4 (GBL_Bits, Image2->bits, GBL_Size);
/*[ JOC ]****************************************************/    
    //PlayersCreateBox ();

		Player1.status = 1;
		Player2.status = 1;
		Player1.time = sin(a*M_PI);
		Player2.time = sin(a*M_PI);
		a+=0.05f;
    PlayersDraw ();
    
    DEFAULT_Flip();
  }


	HSAMPLE s1 = BASS_SampleLoad (false,"samp1.wav",0,0,2,0);
	HSAMPLE s2 = BASS_SampleLoad (false,"samp2.wav",0,0,2,0);
	HSAMPLE s3 = BASS_SampleLoad (false,"samp3.wav",0,0,2,0);

	Player1.life = 100;
	Player2.life = 100;
	Player1.status = 7;
  Player2.status = 7;
	Player1.time = 0;
  Player2.time = 0;
	Player1.timep = 0;
  Player2.timep = 0;
                       
  long oldcount = GetTickCount();
  while ((!Exit) && (Player1.life>0) && (Player2.life>0))
  {
    MISC_MemCpy4 (GBL_Bits, Image->bits, GBL_Size);

		LlumX = 160+80*sin(a);
		PutPartRGB (GBL_Bits,(DWORD *)Flare->bits,LlumX,50,64);
		a+=0.01f;
    //PlayersCreateBox ();

    long count = GetTickCount();

    if (Keys[VK_A]) Player1.x--;
    if (Keys[VK_D])
    {
      if ((Player1.x+50) < Player2.x) Player1.x++;
    }
    if (Keys[VK_SPACE] && (Player1.status==7)) 
    {   
				BASS_SamplePlay (s2);
        Player1.time = 0;
        Player1.status = 2;
    }
    if (Keys[VK_CONTROL] && (Player1.status==7)) 
    {   
				BASS_SamplePlay (s3);
        Player1.time = 0;
        Player1.status = 3;
    }

    if (Keys[VK_LEFT])
    {
      if (Player2.x > Player1.x+50) Player2.x--;
    }
    if (Keys[VK_RIGHT]) Player2.x++;
    if (Keys[VK_INSERT] && (Player2.status==7)) 
    {   
				BASS_SamplePlay (s2);
        Player2.time = 0;
        Player2.status = 2;
    }
    if (Keys[VK_HOME] && (Player2.status==7)) 
    {   
				BASS_SamplePlay (s3);
        Player2.time = 0;
        Player2.status = 3;
    }

		if (Keys[VK_T] || Keys[VK_END])
		{
			GetSomeAra=true;
		}
                            

		if (Keys[VK_F1])
			CheatEnabled1 = true;

		if (Keys[VK_F2])
			CheatEnabled2 = true;

    Player1.timep+=(count-oldcount)/100.0f;                        
    Player2.timep+=(count-oldcount)/100.0f;                            
    Player1.time = sin(Player1.timep);
    Player2.time = sin(Player2.timep);
		if (Player1.timep>M_PI) 
		{            
		  Player1.timep=0;
			if (Player1.status==7)
				Player1.status=8;
			else
				Player1.status=7;
		}
		if (Player2.timep>M_PI)
		{            
		  Player2.timep=0;
			if (Player1.status==7)
				Player2.status=8;
			else
				Player2.status=7;
		}


    PlayersDraw ();
    PlayersCreateBox ();
    int res;
    res = Colisions ();
    if (res == PLAYER1_HIT)
    {
			if (CheatEnabled1) Player2.life-=10;
      Player2.life--;
			PutPartRGB (GBL_Bits,(DWORD *)Flare->bits,Player2.x,Player2.y,64);
      InitParticles (Player2.x,Player2.y,false);			
			BASS_SamplePlay (s1);
    }
    if (res == PLAYER2_HIT)
    { 
			if (CheatEnabled2) Player1.life-=10;
      Player1.life--;
			PutPartRGB (GBL_Bits,(DWORD *)Flare->bits,Player1.x,Player1.y,64);
      InitParticles (Player1.x,Player1.y,true);
			BASS_SamplePlay (s1);
    }         
    Particles ();		
        
		if (GetSomeAra)
		{
			if (GetSomeCount==0)
				GetSomeQuin = rand()%3;
			if (rand()%2)
				FlatternAlpha(GBL_Bits,GBL_Bits,GetSome[GetSomeQuin]->bits,GBL_Size);
			GetSomeCount+=(count-oldcount);
			if (GetSomeCount>1000)
			{
			  GetSomeAra=false;
				GetSomeCount=0;
			}
		}
		
    oldcount = count;
    DEFAULT_Flip();

		RECT r;		
		HDC dc;
		VIDEO_Primary->GetDC (&dc);		
		GetWindowRect (HWnd,&r);
		SetBkColor (dc,0xff00);
		Rectangle (dc,r.left+10,r.top+200,r.left+10+Player1.life,r.top+200+20);
		SetBkColor (dc,0xff00ff);
		Rectangle (dc,r.left+200,r.top+200,r.left+200+Player2.life,r.top+200+20);		
		VIDEO_Primary->ReleaseDC(dc);
	
  }
	while (!Exit)
	{
		DWORD col,col2;
		if (Player1.life<0)	{ col = 0xff; col2 = 0xff0000; }
		else { col = 0xff0000; col2 = 0xff; }

		MISC_MemCpy4 (GBL_Bits, End->bits, GBL_Size);

		PutPartRGB (GBL_Bits, (DWORD *)Flare->bits,90,200,100+100*sin(a));
		RenderNinot2 (90,180,11,sin(a),col,1);
		RenderNinot2 (60,190,10,sin(a),col2,0);
		a+=0.1f;

		DEFAULT_Flip();
	}

  DEFAULT_Close ();
}
