#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include "draw.h"
#include "precalcs.h"
#include "things.h"
#include "atoms.h"
#include "physics.h"
#include "particles.h"
#include "vector.h"
#include "render.h"
#include "panels.h"
#include "fonts.h"
#include "script.h"

extern atom atoms[MAXATOMS];
extern int atom_num;
extern thing balls[MAXBALLS];
extern int ball_num;
extern thing waste[MAXWASTE];
extern int waste_num;
extern thing wasteball[MAXWASTEBALL];
extern int wasteball_num;
extern int wasteballnum[3];
extern int agroup_num;

extern thing crosshair;
extern thing gamecrosshair;
extern image cursor;

extern SDL_Surface *gamescreen;
extern SDL_Surface *screen;
extern SDL_Surface *panel1, *panel2;

extern base bases[MAXBASES];
extern int base_num;


extern colorARGB base_color[2];

extern selection sball[3][2];

extern colorARGB base_active_color;
extern colorARGB base_inactive_color;
extern colorARGB base_choice_color;

extern int playerbase1, playerbase2;

int fps=0, mo=0, kk=0, atime=0;
int frametime;

bool r_pressed_once=false, l_pressed_once=false;
bool spd=true;
bool exw=false;

colorARGB particle_color_random = {0,0,0,0};

int current_level =  1;
level levels[level_num];
bool wait_level_change = false;
bool wait_level_restart = false;

// ==============================

void InitLevels()
{
	int i;
	for (i=0; i<level_num; i++)
	{
		levels[i].bgnum = (i-1) & 1;
	}
}

void PrepareNewLevel()
{
    atom_num = 0;
    ball_num = 0;
    waste_num = 0;
    wasteball_num = 0;
    agroup_num = 0;

    int i, j;
	for (i=0; i<3; i++)
		wasteballnum[i] = 0;
	for (j=0; j<2; j++)
	    for (i=0; i<3; i++)
			sball[i][j].condition = 0;

	InitThings();
	testcreateagroup();
}

void LevelCheck()
{
	int i;
	bool empty = true;

	for (i=0; i<ball_num; i++)
		if (balls[i].exists) empty = false;

	for (i=0; i<atom_num; i++)
		if (atoms[i].exists) empty = false;

	for (i=0; i<waste_num; i++)
		if (waste[i].exists) empty = false;

	for (i=0; i<wasteball_num; i++)
        if (wasteball[i].exists) empty = false;

	for (i=0; i<3; i++)
		if (wasteballnum[i]!=0) empty = false;

	if (empty && !wait_level_change)
	{
		current_level++;
		wait_level_change = true;
		PrepareNewLevel();
	}

	if (wait_level_restart)
	{
		wait_level_change = true;
		PrepareNewLevel();
	}
}

void speeddown(int ticks)
{
    do{}while(SDL_GetTicks() - frametime < ticks);
    frametime = SDL_GetTicks();
}


void Timer()
{
    if (SDL_GetTicks()-atime>=1000)
    {
		atime = SDL_GetTicks();
		mo=(kk-fps);
        fps=kk;
        printf ("%d\n",mo);
    }
}

// --- Keyboard/Mouse ---

int LMB_pressed = 0;
int RMB_pressed = 0;

void mouse_check(int x, int y, bool clicked)
{

	// ==== Over Check ====

	int i, nw;
	float dist, r;
	int con;

	// --- Over base ---

	for (i=0; i<base_num; i++)
	{
		dist = sqrt(pow((bases[i].pos.x-x),2) + pow((bases[i].pos.y-y),2));
		r = bases[i].radius;

		if (!(bases[i].condition & ACTIVE))
		{
		    if (dist<=r)
				bases[i].condition |= CHOICE;
			else
				bases[i].condition &= (~CHOICE);
		}
	}

	// ==== Click Check ====

	// --- Click base ---

	bool outside;

	if (x<0 || y<0)
		outside = false;
	else
	    outside = true;

	if (l_pressed_once)
	{
		for (i=0; i<base_num; i++)
		{
			dist = sqrt(pow((bases[i].pos.x-x),2) + pow((bases[i].pos.y-y),2));
			r = bases[i].radius;
			if (dist<=r && playerbase1==playerbase2)
			{
			    outside = false;
			    playerbase2 = i;
			}
		}

 		if (outside) CreateShoot();
	}
}


void GameKeyCommands()
{
SDL_Event event;
vector mousepos;

	l_pressed_once = false;
	r_pressed_once = false;

	while (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			exw=true;
		break;
		case SDL_KEYDOWN:
			if (event.key.keysym.sym==SDLK_ESCAPE)
				exw = true;
			if (event.key.keysym.sym==SDLK_f)
                spd = !spd;
		break;
		case SDL_MOUSEMOTION:
            crosshair.pos.x = event.motion.x;
            crosshair.pos.y = event.motion.y;
        break;
        case SDL_MOUSEBUTTONUP:
            if (event.button.button == SDL_BUTTON_LEFT)
                LMB_pressed = 0;
			if (event.button.button == SDL_BUTTON_RIGHT)
			    RMB_pressed = 0;

        break;
        case SDL_MOUSEBUTTONDOWN:
            if (event.button.button == SDL_BUTTON_LEFT && LMB_pressed==0)
            {
				l_pressed_once = true;
                LMB_pressed = 1;
                crosshair.pos.x = event.button.x;
			    crosshair.pos.y = event.button.y;
            }
            if (event.button.button == SDL_BUTTON_LEFT && LMB_pressed==0)
            {
				r_pressed_once = true;
                RMB_pressed = 1;
                crosshair.pos.x = event.button.x;
			    crosshair.pos.y = event.button.y;
            }
        break;
		}
	}
	gamecrosshair.pos.x = crosshair.pos.x - PanelScreenWidth;
	gamecrosshair.pos.y = crosshair.pos.y - PanelScreenHeight;
	mouse_check(gamecrosshair.pos.x, gamecrosshair.pos.y, l_pressed_once);
	mouse_panel_check(crosshair.pos.x, crosshair.pos.y, l_pressed_once);
}

void LevelChangeKeyCommands()
{
SDL_Event event;
vector mousepos;

	l_pressed_once = false;
	r_pressed_once = false;

	while (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			exw=true;
		break;
		case SDL_KEYDOWN:
			if (event.key.keysym.sym==SDLK_ESCAPE)
				exw = true;
			wait_level_change = false;
			wait_level_restart = false;
		break;
		case SDL_MOUSEMOTION:
            crosshair.pos.x = event.motion.x;
            crosshair.pos.y = event.motion.y;
        break;
        case SDL_MOUSEBUTTONDOWN:
			wait_level_change = false;
			wait_level_restart = false;
        break;
		}
	}
	gamecrosshair.pos.x = crosshair.pos.x - PanelScreenWidth;
	gamecrosshair.pos.y = crosshair.pos.y - PanelScreenHeight;
	mouse_check(gamecrosshair.pos.x, gamecrosshair.pos.y, l_pressed_once);
	mouse_panel_check(crosshair.pos.x, crosshair.pos.y, l_pressed_once);
}


void ShowCrosshair()
{
    unsigned int *sram = (unsigned int*)screen->pixels;
	RenderCursor(crosshair.pos.x + cursor.width/2, crosshair.pos.y + cursor.height/2, &cursor, sram);
}

void GameScript()
{
    unsigned int *gram = (unsigned int*)gamescreen->pixels;
    ClearAll(gram);
    RunThings();
	RunPanelThings();
    DoPhysics();
    DoParticles();
    ShowAll(gram);
}

void LevelChangeBackground()
{
	float t = SDL_GetTicks()/64.0;
    unsigned int *vram = (unsigned int*)screen->pixels;
	int x, y, yp;
	for (y=0; y<screen->h; y++)
	{
		yp = sin((y+4*t)/45.0)*cos((y-3*t)/63.0)*127 + 128;
	    for (x=0; x<screen->w; x++)
		{
			*vram++ = ((yp>>2)<<16) | (yp>>1);
		}
	}

	char msg1[] = "LEVEL CLEARED";
	char msg2[] = "LIFE LOST";
	char press_key[] = "Press any key!";

	if (!wait_level_restart) DrawText(288, 256, msg1, 4, 1);
	    else DrawText(320, 256, msg2, 4, 1);
	DrawText(280, 384, press_key, 4, 1);
}

void RunChangeLevelScreen()
{
	LevelChangeBackground();
	LevelChangeKeyCommands();
	Timer();
	if (spd) speeddown(16);

	ShowCrosshair();
}

void RunGameScreen()
{
	char lvl[] = "LEVEL ";
	char num[] = "  ";

	GameKeyCommands();
	GameScript();
	Timer();
	if (spd) speeddown(16);

	LevelCheck();
	Blit(gamescreen, screen, PanelScreenWidth, PanelScreenHeight);
	Blit(panel1, screen, 0, PanelScreenHeight);
	Blit(panel2, screen, 0, 0);
	ShowBallSelections();
	ShowWasteBalls();
	ShowCrosshair();

	itoa(current_level, num, 10);
	strcpy(&lvl[6], num);
	DrawText(16, 56, lvl, 2, 1);
}

void Run()
{
	do{
		kk++;
        if (SDL_MUSTLOCK(gamescreen))
            if (SDL_LockSurface(gamescreen) < 0)
                return;

		if (!wait_level_change) RunGameScreen();
		    else RunChangeLevelScreen();

        if (SDL_MUSTLOCK(gamescreen))
            SDL_UnlockSurface(gamescreen);

        SDL_Flip(screen);
	}while(exw==false);
}
