#include "flotski.h"

void SetupGUI() {
	//setup the border for the board area
	borderDecoration = (Fl_Box **)malloc(sizeof(Fl_Box *) * 9);
	borderDecoration[0] = new Fl_Box(13, 28, 7, 7, "");
	borderDecoration[0]->box(FL_UP_BOX);
	borderDecoration[1] = new Fl_Box(20, 30, 120, 5, "");
	borderDecoration[1]->box(FL_UP_BOX);
	borderDecoration[2] = new Fl_Box(140, 28, 7, 7, "");
	borderDecoration[2]->box(FL_UP_BOX);
	borderDecoration[3] = new Fl_Box(140, 35, 5, 150, "");
	borderDecoration[3]->box(FL_UP_BOX);
	borderDecoration[4] = new Fl_Box(140, 185, 7, 7, "");
	borderDecoration[4]->box(FL_UP_BOX);
	borderDecoration[5] = new Fl_Box(110, 185, 30, 5, "");
	borderDecoration[5]->box(FL_UP_BOX);
	borderDecoration[6] = new Fl_Box(20, 185, 30, 5, "");
	borderDecoration[6]->box(FL_UP_BOX);
	borderDecoration[7] = new Fl_Box(13, 185, 7, 7, "");
	borderDecoration[7]->box(FL_UP_BOX);
	borderDecoration[8] = new Fl_Box(15, 35, 5, 150, "");
	borderDecoration[8]->box(FL_UP_BOX);
	
	//setup the rest of the window
	currLevelLbl = new Fl_Box(10, 5, 140, 20, "Current Level:  Pick a level");
	currLevelLbl->labelsize(10);
	totalMovesLbl = new Fl_Box(10, 200, 60, 20, "Total Moves:");
	totalMovesLbl->labelsize(10);
	totalMovesOutput = new Fl_Output(110, 200, 40, 20);
	totalMovesOutput->textsize(10);
	
	doneButton = new Fl_Button(0, 225, 35, 15, "Done");
	doneButton->labelsize(10);
	doneButton->callback((Fl_Callback *)doneButtonPressed);
	resetButton = new Fl_Button(35, 225, 35, 15, "Reset");
	resetButton->labelsize(10);
	resetButton->callback((Fl_Callback *)resetButtonPressed);
	levelButton = new Fl_Menu_Button(70, 225, 35, 15, "Level");
	levelButton->labelsize(10);
	levelButton->menu(levelMenu);
	showBestScoresButton = new Fl_Button(105, 225, 35, 15, "Best");
	showBestScoresButton->labelsize(10);
	showBestScoresButton->callback((Fl_Callback *)showBestScoresButtonPressed);
	aboutButton = new Fl_Button(140, 225, 20, 15, "?");
	aboutButton->labelsize(10);
	aboutButton->callback((Fl_Callback *)aboutButtonPressed);
	
	//setup the about window
	aboutWindow = new Fl_Double_Window(160, 125, "About Flotski");
	
	aboutWindowLbl = (Fl_Box **)malloc(sizeof(Fl_Box *) * 5);
	aboutWindowLbl[0] = new Fl_Box(10, 5, 140, 15, "Flotski");
	aboutWindowLbl[1] = new Fl_Box(10, 20, 140, 15, "Version 1.2");
	aboutWindowLbl[2] = new Fl_Box(10, 35, 140, 15, "Thursday, 21 September 2001");
	aboutWindowLbl[3] = new Fl_Box(10, 60, 140, 15, "Written by Luke Nowak");
	aboutWindowLbl[4] = new Fl_Box(10, 75, 140, 15, "nowakl@mindless.com");
	int i;
	for (i = 0; i < 5; i++)
		aboutWindowLbl[i]->labelsize(10);
		
	aboutDoneButton = new Fl_Button(60, 100, 40, 20, "Done");
	aboutDoneButton->labelsize(10);
	aboutDoneButton->callback((Fl_Callback *)aboutDoneButtonPressed);
	
	aboutWindow->end();
	
	//setup the you win window
	youWinWindow = new Fl_Double_Window(160, 70, "You Win!");
	
	youWinLbl = new Fl_Box(10, 10, 140, 20, "You Win");
	
	youWinDoneButton = new Fl_Button(60, 40, 40, 20, "Done");
	youWinDoneButton->labelsize(10);
	youWinDoneButton->callback((Fl_Callback *)youWinDoneButtonPressed);
	
	youWinWindow->end();
	
	//setup the best scores window
	bestWindow = new Fl_Double_Window(160, 180, "Best Scores");
	
	if ((settings = fopen(settingsName, "r")) == NULL) {
		CreateNewSettings();
	} else {
		fclose(settings);
		GetSavedSettings();
	}
	
	bestDoneButton = new Fl_Button(10, 150, 40, 20, "Done");
	bestDoneButton->labelsize(10);
	bestDoneButton->callback((Fl_Callback *)bestDoneButtonPressed);
	
	bestResetButton = new Fl_Button(110, 150, 40, 20, "Reset");
	bestResetButton->labelsize(10);
	bestResetButton->callback((Fl_Callback *)bestResetButtonPressed);
	
	bestWindow->end();
}

void showBestScoresButtonPressed(Fl_Widget *w, void *data) {
	bestWindow->show(0, 0);
}

void bestDoneButtonPressed(Fl_Widget *w, void *data) {
	bestWindow->hide();
}

void doneButtonPressed(Fl_Widget *w, void *data) {
	SaveSettings();
	
	aboutWindow->hide();
	mainWindow->hide();
}

void resetButtonPressed(Fl_Widget *w, void *data) {
	switch (currLevel) {
	case 0: choseLevel0(0, 0); break;
	case 1: choseLevel1(0, 0); break;
	case 2: choseLevel2(0, 0); break;
	case 3: choseLevel3(0, 0); break;
	case 4: choseLevel4(0, 0); break;
	case 5: choseLevel5(0, 0); break;
	case 6: choseLevel6(0, 0); break;
	}
}

void aboutButtonPressed(Fl_Widget *w, void *data) {
	aboutWindow->show();
}

void BlockButtonPressed(Fl_Widget *w, void *data) {
	int i;
	selectedBlock = (Fl_Button *)w;
	
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->clear();
	}
	largeBlockButton->clear();
	
	selectedBlock->set();
	
	if (selectedBlock->w() == 30 && selectedBlock->h() == 30)
		selectedBlockType = ID_SMALL;
	else if (selectedBlock->w() == 30 && selectedBlock->h() == 60)
		selectedBlockType = ID_LARGEVERT;
	else if (selectedBlock->w() == 60 && selectedBlock->h() == 30)
		selectedBlockType = ID_LARGEHORZ;
	else if (selectedBlock->w() == 60 && selectedBlock->h() == 60)
		selectedBlockType = ID_LARGE;
		
	//clear currently displayed destination buttons
	while (numDestinationBlocks > 0) {
		numDestinationBlocks--;
		mainWindow->remove(destinationButton[numDestinationBlocks]);
	}
	
	//display destination locations
	DisplayDestinationBlocks();
}
	
void DisplayDestinationBlocks() {
	int x = selectedBlock->x(), y = selectedBlock->y(),
		w = selectedBlock->w(), h = selectedBlock->h();
	
	switch (selectedBlockType) {
	case ID_SMALL:
		if (OkToMoveUp(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y - 30, 30, 30, '1');
			
			if (OkToMoveUp(x, y - 30, w, h) == true) {
				DisplayDestinationBlockAt(x, y - 60, 30, 30, '2');
			}
			if (OkToMoveRight(x, y - 30, w, h) == true) {
				DisplayDestinationBlockAt(x + 30, y - 30, 30, 30, '2');
			}
			if (OkToMoveLeft(x, y - 30, w, h) == true) {
				DisplayDestinationBlockAt(x - 30, y - 30, 30, 30, '2');
			}
		}
		if (OkToMoveDown(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y + 30, 30, 30, '1');
			
			if (OkToMoveDown(x, y + 30, w, h) == true) {
				DisplayDestinationBlockAt(x, y + 60, 30, 30, '2');
			}
			if (OkToMoveRight(x, y + 30, w, h) == true) {
				DisplayDestinationBlockAt(x + 30, y + 30, 30, 30, '2');
			}
			if (OkToMoveLeft(x, y + 30, w, h) == true) {
				DisplayDestinationBlockAt(x - 30, y + 30, 30, 30, '2');
			}
		}
		if (OkToMoveRight(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x + 30, y, 30, 30, '1');
			
			if (OkToMoveUp(x + 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x + 30, y - 30, 30, 30, '2');
			}
			if (OkToMoveDown(x + 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x + 30, y + 30, 30, 30, '2');
			}
			if (OkToMoveRight(x + 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x + 60, y, 30, 30, '2');
			}
		}
		if (OkToMoveLeft(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x - 30, y, 30, 30, '1');
			
			if (OkToMoveUp(x - 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x - 30, y - 30, 30, 30, '2');
			}
			if (OkToMoveDown(x - 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x - 30, y + 30, 30, 30, '2');
			}
			if (OkToMoveLeft(x - 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x - 60, y, 30, 30, '2');
			}
		}
	break;
	case ID_LARGEVERT:
		if (OkToMoveUp(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y - 30, 30, 30, '1');
			
			if (OkToMoveUp(x, y - 30, w, h) == true) {
				DisplayDestinationBlockAt(x, y - 60, 30, 30, '2');
			}
		}
		if (OkToMoveDown(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y + 60, 30, 30, '1');
			
			if (OkToMoveDown(x, y + 30, w, h) == true) {
				DisplayDestinationBlockAt(x, y + 90, 30, 30, '2');
			}
		}
		if (OkToMoveRight(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x + 30, y, 30, 60, '1');
		}
		if (OkToMoveLeft(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x - 30, y, 30, 60, '1');
		}
	break;
	case ID_LARGEHORZ:
		if (OkToMoveUp(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y - 30, 60, 30, '1');
		}
		if (OkToMoveDown(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y + 30, 60, 30, '1');
		}
		if (OkToMoveRight(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x + 60, y, 30, 30, '1');
			
			if (OkToMoveRight(x + 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x + 90, y, 30, 30, '2');
			}
		}
		if (OkToMoveLeft(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x - 30, y, 30, 30, '1');
			
			if (OkToMoveLeft(x - 30, y, w, h) == true) {
				DisplayDestinationBlockAt(x - 60, y, 30, 30, '2');
			}
		}
	break;
	case ID_LARGE:
		if (OkToMoveUp(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y - 30, 60, 30, '1');
		}
		if (OkToMoveDown(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x, y + 60, 60, 30, '1');
		}
		if (OkToMoveRight(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x + 60, y, 30, 60, '1');
		}
		if (OkToMoveLeft(x, y, w, h) == true) {
			DisplayDestinationBlockAt(x - 30, y, 30, 60, '1');
		}
	break;
	}
	
	mainWindow->redraw();
}

void DisplayDestinationBlockAt(int x, int y, int w, int h, char label) {
	char *newLabel = (char *)malloc(sizeof(char) * 2);
	newLabel[0] = label;
	newLabel[1] = 0;
	
	destinationButton[numDestinationBlocks]->resize(x + 5, y + 5, w - 10, h - 10);
	destinationButton[numDestinationBlocks]->label(newLabel);
	mainWindow->add(destinationButton[numDestinationBlocks]);
	numDestinationBlocks++;
}

void DestinationButtonPressed(Fl_Widget *w, void *data) {
	Fl_Button *selectedDestination = (Fl_Button *)w;
	int i;
	char *temp;
	
	//move the selected block the the coordinates of this block
	switch (selectedBlockType) {
	case ID_SMALL:
		selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 5);
		
		temp = (char *)malloc(sizeof(char) * 10);
		if (strcmp(selectedDestination->label(), "1") == 0)
			totalMovesCount++;
		else if (strcmp(selectedDestination->label(), "2") == 0)
			totalMovesCount += 2;
			
		sprintf(temp, "%d", totalMovesCount);
		totalMovesOutput->value(temp);
		break;
	case ID_LARGEVERT:
		if (selectedDestination->y() - 5 <= selectedBlock->y())
			selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 5);
		else
			selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 35);
		
		temp = (char *)malloc(sizeof(char) * 10);
		if (strcmp(selectedDestination->label(), "1") == 0)
			totalMovesCount++;
		else if (strcmp(selectedDestination->label(), "2") == 0)
			totalMovesCount += 2;
			
		sprintf(temp, "%d", totalMovesCount);
		totalMovesOutput->value(temp);
		break;
	case ID_LARGEHORZ:
		if (selectedDestination->x() - 5 <= selectedBlock->x())
			selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 5);
		else
			selectedBlock->position(selectedDestination->x() - 35, selectedDestination->y() - 5);
		
		temp = (char *)malloc(sizeof(char) * 10);
		if (strcmp(selectedDestination->label(), "1") == 0)
			totalMovesCount++;
		else if (strcmp(selectedDestination->label(), "2") == 0)
			totalMovesCount += 2;
			
		sprintf(temp, "%d", totalMovesCount);
		totalMovesOutput->value(temp);
		break;
	case ID_LARGE:
		if (selectedDestination->x() - 5 <= selectedBlock->x())
			if (selectedDestination->y() - 5 <= selectedBlock->y())
				selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 5);
			else
				selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 35);
		else
			if (selectedDestination->y() - 5 <= selectedBlock->y())
				selectedBlock->position(selectedDestination->x() - 35, selectedDestination->y() - 5);
			else
				selectedBlock->position(selectedDestination->x() - 5, selectedDestination->y() - 35);
		
		temp = (char *)malloc(sizeof(char) * 10);
		totalMovesCount++;
			
		sprintf(temp, "%d", totalMovesCount);
		totalMovesOutput->value(temp);
		break;
	}
	
	//destroy the destination blocks
	for (i = 0; i < numDestinationBlocks; i++)
		mainWindow->remove(destinationButton[i]);
	
	//unselect all blocks
	for (i = 0; i < numBlocks; i++)
		blockButton[i]->clear();
	largeBlockButton->clear();
	mainWindow->redraw();
	
	//check to see if that was the winning move
	if (largeBlockButton->x() == 50 && largeBlockButton->y() == 125)
		youWinWindow->show();
}

bool OkToMoveLeft(int x, int y, int w, int h) {
	//board area is x=20 y=35 120x150
	int bx, by, bw, bh, i;
	bool allGood = true;
	
	if (x - 30 < 20)
		allGood = false;
	else {
		for (i = 0; i < numBlocks; i++) {
			bx = blockButton[i]->x();
			by = blockButton[i]->y();
			bw = blockButton[i]->w();
			bh = blockButton[i]->h();
			
			if (bw == 30 && bh == 30)
				if (bx == x - 30 && (by == y || by == y + (h - 30)))
					allGood = false;
			if (bw == 30 && bh == 60)
				if (bx == x - 30 && (by == y || by == y + (h - 30) || by + 30 == y))
					allGood = false;
			if (bw == 60 && bh == 30)
				if (bx == x - 60 && (by == y || by == y + (h - 30)))
					allGood = false;
		}
		
		bx = largeBlockButton->x();
		by = largeBlockButton->y();
		if (bx == x - 60 && (by == y || by == y + (h - 30) || by + 30 == y))
			allGood = false;
	}
		
	return allGood;
}

bool OkToMoveRight(int x, int y, int w, int h) {
	//board area is x=20 y=35 120x150
	int bx, by, bw, bh, i;
	bool allGood = true;
	
	if (x + 30 + w > 140)
		allGood = false;
	else {
		for (i = 0; i < numBlocks; i++) {
			bx = blockButton[i]->x();
			by = blockButton[i]->y();
			bw = blockButton[i]->w();
			bh = blockButton[i]->h();
			
			if (bw == 30 && bh == 30)
				if (bx == x + 30 + (w - 30) && (by == y || by == y + (h - 30)))
					allGood = false;
			if (bw == 30 && bh == 60)
				if (bx == x + 30 + (w - 30) && (by == y || by == y + (h - 30) || by + 30 == y))
					allGood = false;
			if (bw == 60 && bh == 30)
				if (bx == x + 30 + (w - 30) && (by == y || by == y + (h - 30)))
					allGood = false;
		}
		
		bx = largeBlockButton->x();
		by = largeBlockButton->y();
		if (bx == x + 30 + (w - 30) && (by == y || by == y + (h - 30) || by + 30 == y))
			allGood = false;
	}
		
	return allGood;
}

bool OkToMoveUp(int x, int y, int w, int h) {
	//board area is x=20 y=35 120x150
	int bx, by, bw, bh, i;
	bool allGood = true;
	
	if (y - 30 < 35)
		allGood = false;
	else {
		for (i = 0; i < numBlocks; i++) {
			bx = blockButton[i]->x();
			by = blockButton[i]->y();
			bw = blockButton[i]->w();
			bh = blockButton[i]->h();
			
			if (bw == 30 && bh == 30)
				if (by == y - 30 && (bx == x || bx == x + (w - 30)))
					allGood = false;
			if (bw == 30 && bh == 60)
				if (by == y - 60 && (bx == x || bx == x + (w - 30)))
					allGood = false;
			if (bw == 60 && bh == 30)
				if (by == y - 30 && (bx == x || bx == x + (w - 30) || bx + 30 == x))
					allGood = false;
		}
		
		bx = largeBlockButton->x();
		by = largeBlockButton->y();
		if (by == y - 60 && (bx == x || bx == x + (w - 30) || bx + 30 == x))
			allGood = false;
	}
		
	return allGood;
}

bool OkToMoveDown(int x, int y, int w, int h) {
	//board area is x=20 y=35 120x150
	int bx, by, bw, bh, i;
	bool allGood = true;
	
	if (y + 30 + h > 195)
		allGood = false;
	else {
		for (i = 0; i < numBlocks; i++) {
			bx = blockButton[i]->x();
			by = blockButton[i]->y();
			bw = blockButton[i]->w();
			bh = blockButton[i]->h();
			
			if (bw == 30 && bh == 30)
				if (by == y + 30 + (h - 30) && (bx == x || bx == x + (w - 30)))
					allGood = false;
			if (bw == 30 && bh == 60)
				if (by == y + 30 + (h - 30) && (bx == x || bx == x + (w - 30)))
					allGood = false;
			if (bw == 60 && bh == 30)
				if (by == y + 30 + (h - 30) && (bx == x || bx == x + (w - 30) || bx + 30 == x))
					allGood = false;
		}
		
		bx = largeBlockButton->x();
		by = largeBlockButton->y();
		if (by == y + 30 + (h - 30) && (bx == x || bx == x + (w - 30) || bx + 30 == x))
			allGood = false;
	}
		
	return allGood;
}

void choseLevel0(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 0;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 0");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 14;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 35, 30, 30, "");
	blockButton[1] = new Fl_Button(20, 65, 30, 30, "");
	blockButton[2] = new Fl_Button(20, 95, 30, 30, "");
	blockButton[3] = new Fl_Button(20, 125, 30, 30, "");
	blockButton[4] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[5] = new Fl_Button(50, 95, 30, 30, "");
	blockButton[6] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[7] = new Fl_Button(80, 95, 30, 30, "");
	blockButton[8] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[9] = new Fl_Button(110, 35, 30, 30, "");
	blockButton[10] = new Fl_Button(110, 65, 30, 30, "");
	blockButton[11] = new Fl_Button(110, 95, 30, 30, "");
	blockButton[12] = new Fl_Button(110, 125, 30, 30, "");
	blockButton[13] = new Fl_Button(110, 155, 30, 30, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}


void choseLevel1(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 1;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 1");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 12;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 95, 30, 30, "");
	blockButton[1] = new Fl_Button(20, 125, 30, 30, "");
	blockButton[2] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[3] = new Fl_Button(50, 95, 30, 30, "");
	blockButton[4] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[5] = new Fl_Button(80, 95, 30, 30, "");
	blockButton[6] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[7] = new Fl_Button(110, 95, 30, 30, "");
	blockButton[8] = new Fl_Button(110, 125, 30, 30, "");
	blockButton[9] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[10] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[11] = new Fl_Button(110, 35, 30, 60, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void choseLevel2(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 2;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 2");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 11;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[1] = new Fl_Button(50, 95, 30, 30, "");
	blockButton[2] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[3] = new Fl_Button(80, 95, 30, 30, "");
	blockButton[4] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[5] = new Fl_Button(110, 95, 30, 30, "");
	blockButton[6] = new Fl_Button(110, 125, 30, 30, "");
	blockButton[7] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[8] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[9] = new Fl_Button(20, 95, 30, 60, "");
	blockButton[10] = new Fl_Button(110, 35, 30, 60, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void choseLevel3(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 3;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 3");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 11;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 95, 30, 30, "");
	blockButton[1] = new Fl_Button(20, 125, 30, 30, "");
	blockButton[2] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[3] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[4] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[5] = new Fl_Button(110, 95, 30, 30, "");
	blockButton[6] = new Fl_Button(110, 125, 30, 30, "");
	blockButton[7] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[8] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[9] = new Fl_Button(110, 35, 30, 60, "");
	blockButton[10] = new Fl_Button(50, 95, 60, 30, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void choseLevel4(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 4;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 4");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 10;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[1] = new Fl_Button(50, 95, 30, 30, "");
	blockButton[2] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[3] = new Fl_Button(80, 95, 30, 30, "");
	blockButton[4] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[5] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[6] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[7] = new Fl_Button(20, 95, 30, 60, "");
	blockButton[8] = new Fl_Button(110, 35, 30, 60, "");
	blockButton[9] = new Fl_Button(110, 95, 30, 60, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void choseLevel5(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 5;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 5");
	
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 10;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[1] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[2] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[3] = new Fl_Button(110, 95, 30, 30, "");
	blockButton[4] = new Fl_Button(110, 125, 30, 30, "");
	blockButton[5] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[6] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[7] = new Fl_Button(110, 35, 30, 60, "");
	blockButton[8] = new Fl_Button(20, 95, 30, 60, "");
	blockButton[9] = new Fl_Button(50, 95, 60, 30, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void choseLevel6(Fl_Widget *w, void *data) {
	//board area is x=20 y=13 120x150
	int i;
	currLevel = 6;
	ResetTotalMoves();
	currLevelLbl->label("Current Level: 6");
		
	//clear board
	ClearBoard();
	
	//make the new board
	numBlocks = 9;
	blockButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * numBlocks);
	blockButton[0] = new Fl_Button(20, 155, 30, 30, "");
	blockButton[1] = new Fl_Button(50, 125, 30, 30, "");
	blockButton[2] = new Fl_Button(80, 125, 30, 30, "");
	blockButton[3] = new Fl_Button(110, 155, 30, 30, "");
	blockButton[4] = new Fl_Button(20, 35, 30, 60, "");
	blockButton[5] = new Fl_Button(110, 35, 30, 60, "");
	blockButton[6] = new Fl_Button(20, 95, 30, 60, "");
	blockButton[7] = new Fl_Button(110, 95, 30, 60, "");
	blockButton[8] = new Fl_Button(50, 95, 60, 30, "");
	blocksInit = true;
		
	largeBlockButton = new Fl_Button(50, 35, 60, 60, "");
	largeBlockInit = true;
	largeBlockButton->color(FL_RED, FL_BLUE);
	largeBlockButton->callback((Fl_Callback *)BlockButtonPressed);
	
	//display the new board
	for (i = 0; i < numBlocks; i++) {
		blockButton[i]->box(FL_EMBOSSED_BOX);
		blockButton[i]->color(FL_RED, FL_BLUE);
		blockButton[i]->callback((Fl_Callback *)BlockButtonPressed);
		mainWindow->add(blockButton[i]);
	}
	mainWindow->add(largeBlockButton);
	
	mainWindow->redraw();
}

void aboutDoneButtonPressed(Fl_Widget *w, void *data) {
	aboutWindow->hide();
}

void youWinDoneButtonPressed(Fl_Widget *w, void *data) {
	youWinWindow->hide();
	
	if (strcmp(bestLbl[currLevel * 2 + 1]->label(), totalMovesOutput->value()) > 1) {
		int totalMovesCount;
		static char *tempStr;
		tempStr = (char *)malloc(sizeof(char) * 10);
		
		sscanf(totalMovesOutput->value(), "%d", &totalMovesCount);
		sprintf(tempStr, "%d", totalMovesCount);
		bestLbl[currLevel * 2 + 1]->label(tempStr);
	}
	
	switch (currLevel) {
	case 0: choseLevel1(0, 0); break;
	case 1: choseLevel2(0, 0); break;
	case 2: choseLevel3(0, 0); break;
	case 3: choseLevel4(0, 0); break;
	case 4: choseLevel5(0, 0); break;
	case 5: choseLevel6(0, 0); break;
	case 6: choseLevel0(0, 0); break;
	}
}

void ClearBoard() {
	int i;
	
	for (i = 0; i < numBlocks; i++)
		mainWindow->remove(blockButton[i]);
	mainWindow->remove(largeBlockButton);
	while (numDestinationBlocks > 0) {
		numDestinationBlocks--;
		mainWindow->remove(destinationButton[numDestinationBlocks]);
	}
	
	mainWindow->redraw();
}

void ResetTotalMoves() {
	char *temp = (char *)malloc(sizeof(char) * 2);
	
	totalMovesCount = 0;
	sprintf(temp, "%d", totalMovesCount);
	totalMovesOutput->value(temp);
	selectedBlockType = 0;
}

void CreateNewSettings() {
	if ((settings = fopen(settingsName, "w")) != NULL) {
		fprintf(settings, "Level0=999999\nLevel1=999999\nLevel2=999999\n");
		fprintf(settings, "Level3=999999\nLevel4=999999\nLevel5=999999\n");
		fprintf(settings, "Level6=999999\n");
		
		fclose(settings);
		
		GetSavedSettings();
	}
}

void GetSavedSettings() {
	char inStr[80];
	static char *tempStr;
	int i, levelNum, scoreNum;
	
	if ((settings = fopen(settingsName, "r")) != NULL) {
		i = 0;
	        bestLbl = (Fl_Box **)malloc(sizeof(Fl_Box *) * 14);
	        while (!feof(settings) && i < 14) {
	        	fgets(inStr, 80, settings);
	        	
	        	sscanf(inStr, "Level%d=%d", &levelNum, &scoreNum);
	        	
	        	tempStr = (char *)malloc(sizeof(char) * 10);
	        	sprintf(tempStr, "Level %d", levelNum);
	        	bestLbl[i] = new Fl_Box(10, 5 + (i * 10), 80, 20, tempStr);
	        	bestLbl[i]->labelsize(10);
	        	
	        	tempStr = (char *)malloc(sizeof(char) * 10);
	        	sprintf(tempStr, "%d", scoreNum);
	        	bestLbl[i + 1] = new Fl_Box(90, 5 + (i * 10), 60, 20, tempStr);
	        	bestLbl[i + 1]->labelsize(10);
	        	
	        	i += 2;
	        }
		
		fclose(settings);
	}
}

void SaveSettings() {
	int i;
	
	if ((settings = fopen(settingsName, "w")) != NULL) {
		for (i = 0; i < 14; i += 2)
			fprintf(settings, "Level%d=%s\n", i / 2, bestLbl[i + 1]->label());
	
		fclose(settings);
	}
}

void bestResetButtonPressed(Fl_Widget *w, void *data) {
	int i;
	
	for (i = 0; i < 14; i += 2) {
		bestLbl[i + 1]->label("999999");
	}
	
	bestWindow->redraw();
}

int main(int argc, char** argv) {
	int i;
	
	mainWindow = new Fl_Double_Window(160, 240, "Flotski");
	
	SetupGUI();
	
	mainWindow->end();
	mainWindow->show(argc, argv);
	choseLevel0(0, 0);
	
	//create the destination blocks for later use
	destinationButton = (Fl_Button **)malloc(sizeof(Fl_Button *) * 4);
	for (i = 0; i < 4; i++) {
		destinationButton[i] = new Fl_Button(5, 5, 20, 20, "");
		destinationButton[i]->box(FL_THIN_UP_BOX);
		destinationButton[i]->color(FL_YELLOW, FL_YELLOW);
		destinationButton[i]->labelcolor(FL_YELLOW);
		destinationButton[i]->callback((Fl_Callback *)DestinationButtonPressed);
	}
	
	return Fl::run();
}
