//==============================================================================
//
// Snake
// -----
// http://www.masterspace.biz/andreschnabel/
// 2006 by André Schnabel (thefrogs@web.de)
//
//==============================================================================

// main.c

#include "globals.h"
#include "utils.h"
#include "splash.h"
#include "apples.h"
#include "snake.h"
#include "map.h"
#include "font.h"

#ifdef DREAMCAST
	#include <kos.h>
	KOS_INIT_FLAGS(INIT_DEFAULT);
	
	extern uint8 romdisk[];
	KOS_INIT_ROMDISK(romdisk);
#endif

SDL_Surface *screen;
Uint8 *keys;

SDL_Surface *bgImg;
SDL_Surface *scoreImgs[MAX_PLAYERS], *gameOverImg, *pauseImg;
SDL_Surface *blockImgs[MAX_PLAYERS], *appleImg, *headImgs[MAX_PLAYERS][4];
SDL_Surface *numbersImg;
SDL_Surface *tileImg;
Uint32 black;

#ifndef NO_SOUND
Mix_Chunk *movSnd, *eatSnd, *gameOverSnd;
Mix_Music *music;
#endif

boolean gameOver, done, pausa = false;
boolean altCtrl = false;
boolean editor = false, fullscreen = SCR_FULLSCREEN;

int numPlayers = 1;
snake_t players[MAX_PLAYERS];
int playersLeft;

void ParseArgs(int argc, char **argv);

void Init(void);
void Quit(void);

void Input(void);
void Update(void);
void Draw(void);

void DrawScore(snake_t *snake);

int main(int argc, char **argv)
{

	#ifdef DREAMCAST
		fs_chdir("/rd/");
		printf("Starting...\n");
	#endif
	
	Uint32 lTime;
	
	ParseArgs(argc, argv);
	SysInit();
	
	done = false;
	
	ShowSplash();
	ShowMenu();
	
	// Load and init everything
	Init();
	
	// Main-loop
	while(!done)
	{
		// Process input
		Input();
		
		if(!gameOver && !pausa)
		{			
			// Do game logic
			Update();
		}
		
		// Draw the scene
		Draw();
			
		// Since we use double buffering...
		SysFlip();
		
		// Don't go over 25fps
		while(SDL_GetTicks() - lTime < 1000 / 25);
		
		lTime = SDL_GetTicks();
			
	};
	
	// Unload all the stuff and shutdown
	Quit();
	return 0;
}

void ParseArgs(int argc, char **argv)
{
	int i;
	
	for(i=1; i<argc; i++)
	{
		if(!strcmp(argv[i], "--editor"))
			editor = true;
		else if(!strcmp(argv[i], "--fullscreen"))
			fullscreen = true;
		else if(!strcmp(argv[i], "--numplayers"))
			numPlayers = argv[i+1][0] - '0';
		else if(!strcmp(argv[i], "--altctrl"))
			altCtrl = true;
	}
}

void Init(void)
{
	int i, j;
	char fname[256];
	
	// Needed to fill the screen with black
	black = SDL_MapRGB(screen->format, 0, 0, 0);
	
	bgImg = LoadImage("background.bmp", false);
	
	for(i=0; i<MAX_PLAYERS; i++)
	{
		sprintf(fname, "block%d.bmp", i+1);
		blockImgs[i] = LoadImage(fname, false);
	}
	
	gameOverImg = LoadImage("gameOver.bmp", true);
	pauseImg = LoadImage("pause.bmp", true);
	appleImg = LoadImage("apple.bmp", true);
	
	for(j=0; j<MAX_PLAYERS; j++)
	{
		for(i=0; i<4; i++)
		{
			sprintf(fname, "head%dp%d.bmp", i, j+1);
			headImgs[j][i] = LoadImage(fname, true);
		}
	}
	
	numbersImg = LoadImage("numbers.bmp", true);
	
	for(i=0; i<MAX_PLAYERS; i++)
	{
		sprintf(fname, "score%d.bmp", i+1);
		scoreImgs[i] = LoadImage(fname, true);
	}
	
	tileImg = LoadImage("tile.bmp", false);
	
#ifndef NO_SOUND
	movSnd = LoadWAV("mov.wav");
	eatSnd = LoadWAV("eat.wav");
	gameOverSnd = LoadWAV("gameover.wav");
	
	music = LoadMUS("music.wav");
	
	Mix_PlayMusic(music, -1);
	Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
#endif
	
	if(!editor)
		LoadMap("map.txt");
	else
	{
		SDL_WM_SetCaption("Snake - Editor - Press 's' to save!", NULL);
		SDL_ShowCursor(true);
		ClearMap();
	}
	
	for(i=0; i<numPlayers; i++)
		InitSnake(&players[i], SNAKE_LENGTH_START, i+1);
	
	InitApples();
	
	gameOver = false;
	playersLeft = numPlayers;
	
	InitMessages();
	AddMessage("Round started!");
}

void Quit(void)
{
	int i, j;
	
	for(i=0; i<numPlayers; i++)
		DeleteBlocks(&players[i]);
	
#ifndef NO_SOUND
	Mix_FreeMusic(music);
	Mix_FreeChunk(gameOverSnd);
	Mix_FreeChunk(eatSnd);
	Mix_FreeChunk(movSnd);
#endif

	SDL_FreeSurface(tileImg);
	
	SDL_FreeSurface(numbersImg);
	
	for(i=0; i<MAX_PLAYERS; i++)
		SDL_FreeSurface(scoreImgs[i]);
	
	for(j=0; j<MAX_PLAYERS; j++)
		for(i=0; i<4; i++)
			SDL_FreeSurface(headImgs[j][i]);
	
	SDL_FreeSurface(appleImg);
	SDL_FreeSurface(pauseImg);
	SDL_FreeSurface(gameOverImg);
	
	for(i=0; i<MAX_PLAYERS; i++)
		SDL_FreeSurface(blockImgs[i]);
	
	SDL_FreeSurface(bgImg);
	
	SysQuit();
}

void RestartRound(void)
{
	int i;
	for(i=0; i<numPlayers; i++)
	{
		DeleteBlocks(&players[i]);
		InitSnake(&players[i], SNAKE_LENGTH_START, i+1);
	}
	
	InitApples();
	gameOver = false;
	playersLeft = numPlayers;
	AddMessage("Round restarted!");
}

void Input(void)
{	
	int i;
	static boolean pauseReleased = false;
	
	SysInput();
		
	if(keys[SDLK_PAUSE])
	{
		if(pauseReleased)
		{
			pausa = !pausa;
			pauseReleased = false;
		}
	}
	else
		pauseReleased = true;
	
	if(gameOver)
		if(keys[SDLK_RETURN])
			RestartRound();
	
	if(pausa || gameOver)
		return;
	
	if(editor)
	{
		static int mouseX, mouseY;
		
		if(SDL_GetMouseState(&mouseX, &mouseY) & SDL_BUTTON(1))
			map[mouseY / BLOCK_H][mouseX / BLOCK_W] = 1;
		else if(SDL_GetMouseState(&mouseX, &mouseY) & SDL_BUTTON(3))
			map[mouseY / BLOCK_H][mouseX / BLOCK_W] = 0;
		
		if(keys[SDLK_s])
			SaveMap("map.txt");
		
		return;
	}
	
	for(i=0; i<numPlayers; i++)
	{
		switch(i+1)
		{
			case 1:
				UpdateKey(&players[i].kLeft, SDLK_LEFT);
				UpdateKey(&players[i].kRight, SDLK_RIGHT);
				UpdateKey(&players[i].kUp, SDLK_UP);
				UpdateKey(&players[i].kDown, SDLK_DOWN);
				break;
			case 2:
				UpdateKey(&players[i].kLeft, SDLK_a);
				UpdateKey(&players[i].kRight, SDLK_d);
				UpdateKey(&players[i].kUp, SDLK_w);
				UpdateKey(&players[i].kDown, SDLK_s);
				break;
			case 3:
				UpdateKey(&players[i].kLeft, SDLK_f);
				UpdateKey(&players[i].kRight, SDLK_h);
				UpdateKey(&players[i].kUp, SDLK_t);
				UpdateKey(&players[i].kDown, SDLK_g);
				break;
			case 4:
				UpdateKey(&players[i].kLeft, SDLK_j);
				UpdateKey(&players[i].kRight, SDLK_l);
				UpdateKey(&players[i].kUp, SDLK_i);
				UpdateKey(&players[i].kDown, SDLK_k);
				break;
		}
		
		if(IsPressed(players[i].kLeft))
		{
			if(!altCtrl)
			{
				if(players[i].dir != DIR_LEFT)
					players[i].dir--;
				else
					players[i].dir = DIR_DOWN;				
			}
			else
				players[i].dir = DIR_LEFT;
		}
		
		if(IsPressed(players[i].kRight))
		{
			if(!altCtrl)
			{
				if(players[i].dir != DIR_DOWN)
					players[i].dir++;
				else
					players[i].dir = DIR_LEFT;
			}
			else
				players[i].dir = DIR_RIGHT;
		}
		
		if(IsPressed(players[i].kUp) && altCtrl)
			players[i].dir = DIR_UP;
		if(IsPressed(players[i].kDown) && altCtrl)
			players[i].dir = DIR_DOWN;
	}
}

void Update(void)
{
	int i;
	
	if(editor)
		return;
	
	for(i=0; i<numPlayers; i++)
		UpdateSnake(&players[i]);
	
	UpdateApples();	
	UpdateMessages();
}

void Draw(void)
{
	int i;
	static SDL_Rect rect;
	
	// Clean our screen
	//SDL_FillRect(screen, NULL, black);
	SDL_BlitSurface(bgImg, NULL, screen, NULL);
	
	DrawMap();
	
	if(editor)
		return;
	
	for(i=0; i<numPlayers; i++)
		DrawSnake(&players[i]);
	
	DrawApples();	
	DrawMessages(10, 10);
	
	for(i=0; i<numPlayers; i++)
		DrawScore(&players[i]);
	
	// Game over?
	if(gameOver)
	{
		rect.w = gameOverImg->w;
		rect.h = gameOverImg->h;
		
		rect.x = (SCR_W - rect.w) / 2;
		rect.y = (SCR_H - rect.h) / 2;
		
		SDL_BlitSurface(gameOverImg, NULL, screen, &rect);
	}
	
	// pausa?
	if(pausa)
	{
		rect.w = pauseImg->w;
		rect.h = pauseImg->h;
		
		rect.x = (SCR_W - rect.w) / 2;
		rect.y = (SCR_H - rect.h) / 2;
		
		SDL_BlitSurface(pauseImg, NULL, screen, &rect);
	}
}

// Draws the score
void DrawScore(snake_t *snake)
{
	int i;
	static SDL_Rect srcRect, destRect;
	char scoreAsStr[100];
	
	destRect.w = scoreImgs[snake->nr - 1]->w;
	destRect.h = scoreImgs[snake->nr - 1]->h;
	
	destRect.x = 450;
		
	switch(snake->nr)
	{
		case 1:
			destRect.y = 10;
			break;
		case 2:
			destRect.y = 30;
			break;
		case 3:
			destRect.y = 50;
			break;
		case 4:
			destRect.y = 70;
			break;
	}
	
	
	SDL_BlitSurface(scoreImgs[snake->nr - 1], NULL, screen, &destRect);
	
	srcRect.w = destRect.w = 13;
	srcRect.h = destRect.h = 18;
	srcRect.y = 0;
	
	sprintf(scoreAsStr, "%d", snake->score);
	
	for(i=0; i<strlen(scoreAsStr); i++)
	{
		srcRect.x = (scoreAsStr[i] - '0') * srcRect.w;
		destRect.x = 540 + i * destRect.w;
		
		SDL_BlitSurface(numbersImg, &srcRect, screen, &destRect);
	}
}
