#include "board.h"
#include "string.h"
#include "data3.h"


BOARD::BOARD()
{
	init();
}

BOARD::~BOARD()
{

}

void BOARD::set_difficulty(int iValue)
{
	iDifficulty = iValue;
}


void BOARD::resetup(games gCurrent_Game, int Row_Count, float fPercent, int iTime)
{
	int bx, by;

	if(Row_Count > MAX_ROWS) Row_Count = MAX_ROWS;
	iRow_Count = MID(0, Row_Count, 30);
	arrange_tiles(iWidth, iPadding, Row_Count);

	bx = iSpace + iPadding;
	by = iSpace + iPadding;
	iConsecutive = 0;

	alive = true;

	fPCurrent_Max = fPercent;
	fPMax = fPercent;

	
	pToggle_Progress->resetup(GOLD, MASK, fPCurrent_Max);	
	pToggle_Progress->set_bar(fPCurrent_Max);
	pToggle_Progress->set_progress(0.0);

	bParticle_Effect = true;
	ultima = false;
	ultima_timer = 0;
	ultima_size = 0;
	ultima_trans = 0;
	ultima_complete = false;

	iTimer = iTime;	
	reset_clock();

	clear_bonuses();

	// Re-setup Toggle-specific data...
	for(int j = 0; j < Row_Count; j++)
	{
		if(j != 0) bx += iSize + iSpace;
		by = iSpace + iPadding;
		for(int k = 0; k < Row_Count; k++)
		{			
			if(k != 0) by += iSize + iSpace;
			
			if(rand() % 100 > 80) 
				tToggles[j][k]->setup(gCurrent_Game, bx, by, iSize, iSize, false, iDifficulty);
			else
				tToggles[j][k]->setup(gCurrent_Game, bx, by, iSize, iSize, true, iDifficulty);
		}
	}

	iTimer_Offset = ticks;
}

void BOARD::draw_type(BITMAP *bDisplay, int index)
{
	stretch_sprite(bDisplay, bType[index], 0, 0, bDisplay->w, bDisplay->h);
}


void BOARD::setup(int W, int H, int Padding, char *cpath, char *cpath1, char *cpath2)
{
	bType[0] = load_bitmap_check(cpath, NULL);
	bType[1] = load_bitmap_check(cpath1, NULL);
	bType[2] = load_bitmap_check(cpath2, NULL);	

	iWidth = W;
	iHeight = H;
	bImage = create_bitmap_check(W, H);
	iPadding = Padding;
		
	pToggle_Progress = new PROGRESS_BAR;
	pToggle_Progress->setup(400, 50, false);

	oHelp_Button = new OPTION;
	oHelp_Button->setup("", 101, BUTTON, 440, 410, 190, 60, 101, 0);
	oHelp_Button->set_button_text("Help", 0);	
	oHelp_Button->highlight_only();
	
	

	for(int j = 0; j < MAX_ROWS; j++)
		for(int k = 0; k < MAX_COLUMNS; k++)		
			tToggles[j][k] = new TOGGLE;

	for(int b = 0; b < MAX_BONUSES; b++)
		bGift[b] = new BONUS;
		
	
}


void BOARD::destroy_bonuses()
{
	for(int i = 0; i < MAX_BONUSES; i++)
		if(bGift[i] != NULL)
		{
			bGift[i]->destroy();			
			bGift[i] = NULL;
		}

	for(int h = 0; h < MAX_SLOTS; h++)
		bSlots[h] = NULL;
}

void BOARD::reset_bonuses()
{
	for(int h = 0; h < MAX_SLOTS; h++)
		bSlots[h] = NULL;
}


void BOARD::destroy()
{
	if(bImage != NULL) destroy_bitmap(bImage);
	if(bType[0] != NULL) {destroy_bitmap(bType[0]); bType[0] = NULL;}
	if(bType[1] != NULL) {destroy_bitmap(bType[1]); bType[1] = NULL;}
	if(bType[2] != NULL) {destroy_bitmap(bType[2]); bType[2] = NULL;}
	if(oHelp_Button != NULL) {oHelp_Button->destroy(); oHelp_Button = NULL;}
	if(pToggle_Progress != NULL) pToggle_Progress->destroy();

	for(int j = 0; j < iRow_Count; j++)
		for(int k = 0; k < iRow_Count; k++)
			if(tToggles[j][k] != NULL) 
			{
				tToggles[j][k]->destroy();
				tToggles[j][k] = NULL;
			}
	for(int i = 0; i < MAX_BONUSES; i++)
		if(bGift[i] != NULL)
		{
			bGift[i]->destroy();
			bGift[i] = NULL;
		}

	for(int h = 0; h < MAX_SLOTS; h++)
		bSlots[h] = NULL;

}


void BOARD::clear_bonuses()
{
	bool safe;
	for(int i = 0; i < MAX_BONUSES; i++)
		if(bGift[i] != NULL)
		{
			safe = true;
			for(int j = 0; j < MAX_SLOTS; j++)
				if(bGift[i] == bSlots[j])
					safe = false;
				if(safe == true)
				{
					//bGift[i]->destroy();
					//bGift[i] = NULL;
					bGift[i]->visible = false;
				}
		}				
}

void BOARD::slide_bonuses()
{
	BONUS *bTemp;

	if(bSlots[0] != NULL)bSlots[0]->place(bSlots_X[MAX_SLOTS - 1], bSlots_Y[MAX_SLOTS - 1]);
	bTemp = bSlots[0];
	for(int i = 0; i < MAX_SLOTS - 1; i++)
	{
		if(bSlots[i+1] != NULL) bSlots[i+1]->place(bSlots_X[i], bSlots_Y[i]);
		bSlots[i] = bSlots[i + 1];
	}
	bSlots[MAX_SLOTS - 1] = bTemp;

}
void BOARD::update(games &gCurrent_Game)
{
	int iCount = 0;	
	bool status;
	input(gCurrent_Game);
	
	status = true;
	poll_mouse();
	for(int j = 0; j < iRow_Count; j++)
		for(int k = 0; k < iRow_Count; k++)
		{
			tToggles[j][k]->update(gCurrent_Game, mouse_x - 20, mouse_y - 20);	
			if(ultima_complete) tToggles[j][k]->toggle_down(gCurrent_Game);
			if(tToggles[j][k]->is_visible() != true) 
				iCount++;
			else
				if(tToggles[j][k]->iType() != 3)
					status = false;
		}	

	// Got 100% of Toggles down!!!!!!!!!!
	if(status) 
	{
		alive = false;
		if(!ultima)gCurrent_Game.gScore->add(100 * gCurrent_Game.level);
		gCurrent_Game.audio.play_sfx(2);
		gCurrent_Game.pPenalty_Screen->move(120, 40);
	}
	
	for(int i = 0; i < MAX_BONUSES; i++)
		if(bGift[i] != NULL) 
		{
			bGift[i]->update(gCurrent_Game, mouse_x - 20, mouse_y - 20);
			if(ultima) 
			{
				clear_bonuses();				
			}
		}
	fPercentage = float(iCount) / float(iRow_Count * iRow_Count);	
	iCurrent_Time = ticks - iTimer_Offset;
	fTime = (iCurrent_Time) / float(iTimer);

	pToggle_Progress->set_progress(fPercentage);	
	pToggle_Progress->update();

	if(pToggle_Progress->finished() && bParticle_Effect)
	{	
		gCurrent_Game.gScore->add(50);
		gCurrent_Game.audio.play_sfx(3);
		gCurrent_Game.peToggle_Stars->explode(150, 210, 445, 200, 25, 1.0, 0.01, 1.0, 0.05, 60);
		bParticle_Effect = false;
	}
	if(gCurrent_Game.pTime_Progress->finished())
	{
        alive = false;
		if(!pToggle_Progress->finished()) 
			board_game_over(gCurrent_Game);			
		else
		{
			if(!ultima)
			{
			gCurrent_Game.audio.play_sfx(2);
			gCurrent_Game.pPenalty_Screen->move(120, 40);
			}
		}
	}
	
	if(ultima && !ultima_complete && abs(ticks - ultima_timer) > 2)
	{
		ultima_trans += 4;
		if(ultima_trans > 255) 
		{
			ultima_trans = 255;
			ultima_complete = true;
			gCurrent_Game.peToggle_Stars->explode(MAX_PARTICLES, 200, 200, 200, 200, 1.0, 0.01, 1.0, 0.05, 100, 0.5);
		}
		ultima_size += 5;
		ultima_timer = ticks;
	}
	if(ultima_complete && abs(ticks - ultima_timer) > 2)
	{
		ultima_trans -= 10;
		if(ultima_trans < 0)
		{
			ultima_trans = 0;
			ultima = false;
			ultima_complete = false;
		}
	}
	

	if(abs(ticks - Combo_Timer) > 180)
	{
		//This code is a little sloppy, but it gets the job done...
		if(bFourth_Combo == true)
		{
			iConsecutive -= FOURTH_COMBO;
			bFirst_Combo = false;
			bSecond_Combo = false;
			bThird_Combo = false;
			bFourth_Combo = false;
		}
		
		if(bThird_Combo == true)
		{
			iConsecutive -= THIRD_COMBO;
			bFirst_Combo = false;
			bSecond_Combo = false;
			bThird_Combo = false;
		}
		if(bSecond_Combo == true)
		{
			iConsecutive -= SECOND_COMBO;
			bFirst_Combo = false;			
			bSecond_Combo = false;
		}
		if(bFirst_Combo == true)
		{
			iConsecutive -= FIRST_COMBO;
			bFirst_Combo = false;			
		}
	}
	if(iConsecutive < 10)
	{
		bFirst_Combo = false;
		bSecond_Combo = false;
		bThird_Combo = false;
		bFourth_Combo = false;
		Combo_Timer = ticks;		
	}

	oHelp_Button->update();
	if(oHelp_Button->click() != 0)		//Help Button was clicked...
	{
		GAME.state = PAUSED;
		GAME.audio.stop();
		GAME.MainMenu->change_menu(7);
		GAME.pause_ticks = ticks;
		GAME.pause_system = system_time;
		
	}
		
}

void BOARD::board_game_over(games &gCurrent_Game)
{
	BITMAP *bTemp;
	BITMAP *bText;
	BITMAP *bHigh;
	char cName[CHAR_SIZE];
	int val = 0;
	int i = 0;
	bool copy;

	gCurrent_Game.audio.play_sfx(6);	
		
	BITMAP *bGame_Over = (BITMAP *) GAME.dat3[GAMEOVER].dat;
	BITMAP *bDim = create_bitmap_check(GAME.configuration->w, GAME.configuration->h);
	rectfill(bDim, 0, 0, bDim->w, bDim->h, BLACK);
	int iTrans = 0;
	while(iTrans < 80)
	{
		iTrans += 20;
		set_trans_blender(0,0,0, iTrans);
        draw_trans_sprite(buffer, bGame_Over, 200, 50);
		
		draw_sprite(screen, buffer, 0, 0);
		rest(50);
	}

	set_trans_blender(0,0,0, 120);
	draw_trans_sprite(buffer, bDim, 0, 0);
	
	draw_sprite(buffer, bGame_Over, 200, 50);		
	draw_sprite(screen, buffer, 0, 0);

		
	gCurrent_Game.low_score = gCurrent_Game.gHSC->get_low();
	if(gCurrent_Game.gScore->points > gCurrent_Game.low_score)
	{	
		gCurrent_Game.audio.play_sfx(2);
		strcpy(cName, gCurrent_Game.cName);

		bTemp = create_bitmap_check(300, 50);
		bText = create_bitmap_check(300, 50);
		bHigh = (BITMAP *) GAME.dat3[HIGHSCORE].dat;
		set_palette((RGB *) gCurrent_Game.score_palette);

		// Quickly hacked routine
		i = strlen(cName);
		clear_keybuf();
		while(val != 13 && val != 27)
		{
			
			ticks++;
			if(keypressed())
			{
				val = readkey() & 0xff;
				if(val != 8)
				{	
					if(i < CHAR_SIZE - 1 && val != 13 && val != 27) 
					{
						cName[i++] = val;
						cName[i] = '\0';
					}
				}
				else
				{
					i = MID(0, i - 1, CHAR_SIZE - 1);
					cName[i] = '\0';
				}		
			}


			rectfill(bTemp, 0, 0, bTemp->w, bTemp->h, BLACK);
			rectfill(bText, 0, 0, bText->w, bText->h, MASK);
			rect(bTemp, 1, 1, bTemp->w - 1, bTemp->h - 1, LIGHTGOLDENRODYELLOW);
			rect(bTemp, 2, 2, bTemp->w - 2, bTemp->h - 2, LIGHTGOLDENROD);
			line(bTemp, (i + 1) * 18, 2, (i + 1) * 18, bTemp->h - 2, GREEN);
			line(bTemp, (i + 1) * 18 + 1, 2, (i + 1) * 18 + 1, bTemp->h - 2, GREEN);

		
			textprintf_ex(bText, GAME.score_font, 10, 10, -1, -1, "%s", cName);
			textprintf_ex(buffer, GAME.score_font, 170, 370, -1, -1,"Enter Name:");
			draw_sprite(bTemp, bText, 0, 0);
			draw_sprite(buffer, bTemp, 170, 400);			
			
			draw_sprite(buffer, bGame_Over, 200, 50);			
			draw_sprite(buffer, bHigh, 150, 200);
			
			
			draw_sprite(screen, buffer, 0, 0);
		}

		copy = false;
		//check name
		for(unsigned int c = 0; c < strlen(cName); c++)
		{
			if(cName[c] != ' ' && cName[c] != '\0' && cName[c] != '\n')
				copy = true;
		}

		if(copy == true)
			strcpy(gCurrent_Game.cName, cName);
		else
			strcpy(gCurrent_Game.cName, "Anonymous");

		gCurrent_Game.gHSC->local_update();
		gCurrent_Game.gHSC->get_local();

		if(gCurrent_Game.gHSC->online_check())
			gCurrent_Game.gHSC->online_submit();

		destroy_bitmap(bText);
		destroy_bitmap(bTemp);		
	}	
	else
	{
		clear_keybuf();
		while(!keypressed())
		{
			textprintf_ex(buffer, GAME.score_font, 170, 370, -1, -1, "Press any key...");
			draw_sprite(screen, buffer, 0, 0);
		}
	}
	
	destroy_bitmap(bDim);

	GAME.state = TITLE_SCREEN;
	GAME.MainMenu->reset();
	GAME.audio.stop();


}

void BOARD::input(games gCurrent_Game)
{
	if(abs(ticks - input_timer) > 1 && input_lock == false)
	{
		if(gInput.MAP(ACCEPT) || mouse_b & 1)
		{
			use_bonus(gCurrent_Game);
			input_lock = true;	
		}
		
		if(gInput.MAP(ACTION_1) || mouse_b & 2)
		{
			input_lock = true;	
			slide_bonuses();
		}

		
		input_timer = ticks;
		

	}

	if(input_lock == true)
	{
		if(!gInput.MAP(ACCEPT) && !gInput.MAP(ACTION_1) && !(mouse_b & 1) && !(mouse_b & 2))
			input_lock = false;
	}


}

void BOARD::use_bonus(games gCurrent_Game)
{
	int i = 0, j = 0;
	while(i < MAX_SLOTS && bSlots[i] == NULL)
		i++;
	if(i >= MAX_SLOTS) return;

	while(j < MAX_BONUSES && bGift[j] != bSlots[i])
		j++;

	if(j >= MAX_BONUSES) return;
	if(bGift[j]->use(gCurrent_Game))
	{
		//bGift[j]->destroy();
		//bGift[j] = NULL;
		bGift[j]->visible = false;
		bSlots[i] = NULL;
		slide_bonuses();
	}
}

int BOARD::tile_size()
{
	return iSize;
}

void BOARD::generate_bonus(int iDifficulty, int x, int y)
{
	int i = 0;
	int moderation = 5;  //Programmer variable to balance bonus-giving system
	int bonus_type;
	while(i < MAX_BONUSES)
	{
		if(!bGift[i]->visible)
			break;
		i++;
	}

	if(i >= MAX_BONUSES)
		return;
	else
	{
		//Decide if we are even going to get a bonus
		if(rand() % 100 < (iDifficulty / moderation))
		{
			
			bonus_type = rand() % (1000 + (GAME.level * 5));
			if(bonus_type <= 1000 && bonus_type > 500)
			{
				
				bGift[i]->reset(BOMB, "./data/images/bomb.pcx", x, y, 32, 32, 4, iSize);			
			}
			else if(bonus_type <= 500 && bonus_type > 250)
			{				
				bGift[i]->reset(BOLT, "./data/images/bolt.pcx", x, y, 32, 32, 4, iSize);			
			}
			else if(bonus_type <= 250 && bonus_type > 80)
			{
				//Currently, the Blue Turtle shell isn't in-game :/								
			}
			
			else if(bonus_type <= 80 && bonus_type > 30)
			{
				
				bGift[i]->reset(CLOCK, "./data/images/clock.pcx", x, y, 32, 32, 12, iSize);
			}
			else if(bonus_type <= 30 && bonus_type > 10)
			{
				
				bGift[i]->reset(BPERCENT, "./data/images/percent.pcx", x, y, 32, 32, 8, iSize);			
			}
			else if(bonus_type <= 10)
			{
				
				bGift[i]->reset(ULTIMA, "./data/images/ultima.pcx", x, y, 32, 32, 8, iSize);			
			}
			
		}
				
	}
}

void BOARD::draw(games gCurrent_Game)
{
	//rectfill(bImage, 0, 0, bImage->w, bImage->h, MASK);	
	stretch_sprite(bImage, gCurrent_Game.bWater, 0, 0, bImage->w, bImage->h);
	for(int j = 0; j < iRow_Count; j++)
		for(int k = 0; k < iRow_Count; k++)
			tToggles[j][k]->draw(bImage);	

	pToggle_Progress->draw();
	gCurrent_Game.sToggles_Screen->draw_object(2, pToggle_Progress->bDraw(), 0, 0);
	gCurrent_Game.sToggles_Screen->draw_rectangle(2, 0, 0, 399, 49, LIGHTGOLDENRODYELLOW);
	gCurrent_Game.sToggles_Screen->draw_rectangle(2, 1, 1, 398, 48, LIGHTGOLDENROD);
	
	if(ultima)
	{
		set_trans_blender(0,0,0,ultima_trans);
		drawing_mode(DRAW_MODE_TRANS, bImage, 0,0);
		circlefill(bImage, 200, 200, ultima_size, GREEN);		
		drawing_mode(DRAW_MODE_SOLID, bImage, 0,0);
	}
	
}

void BOARD::draw_buttons(BITMAP *bDisplay)
{
	oHelp_Button->draw(bDisplay);
	rect(bDisplay, 440, 410, 630, 470, LIGHTGOLDENRODYELLOW);
	rect(bDisplay, 441, 411, 629, 469, LIGHTGOLDENROD);			
}

void BOARD::draw_bonuses(BITMAP *bDisplay)
{
	if(ultima) return;
	for(int i = 0; i < MAX_BONUSES; i++)
		if(bGift[i] != NULL && bGift[i]->visible) 
			bGift[i]->draw(bDisplay, iSize, iSize);

}

BITMAP *BOARD::image()
{
	return bImage;
}



void BOARD::arrange_tiles(int Board_Size, int Padding, int Row_Count)
{
  	int iExtra = 2;
 	int iRemainder = 0, iEmpty = 0;

    if(Row_Count == 0) return;
	iSize = (Board_Size - (Padding * 2)) / (Row_Count + iExtra);  
    iRemainder = (Board_Size - (Padding * 2)) - (iSize * (Row_Count + iExtra));
 	iEmpty = iSize * iExtra + iRemainder;
 	iSpace = iEmpty / (Row_Count + 1);    
}

bool BOARD::complete()
{
	return alive;
}

void BOARD::init()
{
	for(int x = 0; x < MAX_ROWS; x++)
		for(int y = 0; y < MAX_COLUMNS; y++)
            tToggles[x][y] = NULL;
	for(int i = 0; i < MAX_BONUSES; i++)
		bGift[i] = NULL;

	for(int z = 0; z < MAX_SLOTS; z++)
	{
		bSlots[z] = NULL;		
		if(z <= 2)
		{
            bSlots_X[z] = 450 + (z * 60) - 5;
			bSlots_Y[z] = 280;
		}
		else
		{
			bSlots_X[z] = 450 + ((z - 3) * 60) - 5;
			bSlots_Y[z] = 280 + 60;
		}
	}

	

	iRow_Count = 0;
	fPercentage = 0.0;

	iSize = 0;
	iSpace = 0;

	iWidth = 0;
	iHeight = 0;
	iPadding = 0;	
	fTime = 0.0;
	iCurrent_Time = 0;
	iTimer = 0;
	iTimer_Offset = 0;
	iConsecutive = 0;

	bFirst_Combo = false;
	Combo_Timer = 0;
	input_timer = 0;

	fPCurrent_Max = 0.0;
	fPMax = 0.0;

	alive = false;
	input_lock = false;

	pToggle_Progress = NULL;
	bParticle_Effect = false;

	ultima = false;
	ultima_timer = 0;
	ultima_size = 0;
	ultima_trans = 0;
	ultima_complete = false;

	oHelp_Button = NULL;
	

}

void BOARD::set_timer(int iTime)
{
	iTimer = iTime;
}

void BOARD::set_progress_max(float fNeeded)
{
	fPCurrent_Max = fNeeded;
	pToggle_Progress->set_bar(fNeeded);
}

float BOARD::progress_max()
{
	return fPCurrent_Max;
}
	

void BOARD::reset_clock()
{
	iTimer_Offset = ticks;
}


int BOARD::current_slot()
{
	int i = 0;
	while(i < MAX_SLOTS && bSlots[i] != NULL)
		i++;
	if(i >= MAX_SLOTS) return -1;
	return i;
}

void BOARD::set_slot(int i, BONUS *bTemp)
{
	bSlots[i] = bTemp;
}

int BOARD::toggle_x(int mx, int my)
{
	int j = 0, k = 0;
	bool status = false;
	while(j < iRow_Count && status == false)
	{
		k = 0;
		while(k < iRow_Count && status == false)
		{
			status = tToggles[j][k]->mouse_over(mx, my);

			k++;
		}
		j++;
	}
	return j - 1;
}

int BOARD::toggle_y(int mx, int my)
{
	int j = 0, k = 0;
	bool status = false;
	while(j < iRow_Count && status == false)
	{
		k = 0;
		while(k < iRow_Count && status == false)
		{
			status = tToggles[j][k]->mouse_over(mx, my);

			k++;
		}
		j++;
	}
	return k - 1;
}

void BOARD::toggle_down(games gCurrent_Game, int i, int j)
{
	if(i >= 0 && i < iRow_Count && j >= 0 && j < iRow_Count)
		tToggles[i][j]->toggle_down(gCurrent_Game);
}

