/*
   Copyright (C) 2004 by James Gregory
   Part of the GalaxyHack project
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.
 
   See the COPYING file for more details.
*/

#include "ForceSelect.h"

#include "Globals.h"
#include "RTSInlines.h"
#include "PreBattle.h"

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

namespace ForceSelect {

LoadSideDW::LoadSideDW():
LargeBlankDW("Edit a fleet or create a new one. Right click to copy or delete.") {}

LoadSideDW::~LoadSideDW() {
	if (!sides.size())
		gsTo = GST_MainMenu;
}

LoadSideSM::LoadSideSM(int iParentID):
FileListMenu(iParentID) {
	ExpensiveUpdate();
}

void LoadSideSM::ExpensiveUpdate() {
	ClearItems();

	MenuItem tempItem;
	tempItem.desc = "New";
	tempItem.choice = FS_NewSide;
	AddItem(tempItem);

	AddBlankItem();
    AddFleets(FS_LoadSide);

	InitBorder();
}

bool LoadSideSM::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case FS_NewSide:
			myWindows.push_back(GenWindow(0, 0, FS_NewSideName, 0, 0, 0));
			break;

		case FS_LoadSide:
			ForceSelect::LoadSide(currentSelection.desc, false);
			closed = true;
			break;
		}
	} else if (currentSelection.choiceType == MCT_RightCursor) {
		switch (currentSelection.choice) {
		case FS_NewSide:
			break;

		case FS_LoadSide:
			myWindows.push_back(GenWindow(x, y, FS_LoadSidePU, currentSelection.desc, myID, 0));
			break;
		}
	}

	return false;
}

LoadSidePU::LoadSidePU(int ix, int iy, const string& iSideName, int iParentID):
PopupMenu(ix, iy, iParentID, 0), sideName(iSideName) {
	MenuItem tempItem;
	
	tempItem.desc = "Copy fleet: " + sideName;
	tempItem.choice = FS_CopyFleet;
	AddItem(tempItem);
	
	tempItem.desc = "Delete fleet: " + sideName;
	tempItem.choice = FS_DeleteFleet;
	AddItem(tempItem);
	
	InitRects();
}

bool LoadSidePU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_CopyFleet:
			myWindows.push_back(GenWindow(0, 0, FS_CopyFleet, sideName, parentID, 0));
			closed = true;
			break;
			
		case FS_DeleteFleet:
			myWindows.push_back(GenWindow(0, 0, FS_DeleteFleet, sideName, parentID, 0));
			closed = true;
			break;
		}
	}

	return false;
}

NewSideName::NewSideName():
StringInputBox(maxNameLength, none_constant, 0) {
	title = "What do you wish to call your new side?";

	rect.w = 400;
	rect.h = 100;

	CentreWindow();

	InitRects();
}

bool NewSideName::Keyboard(SDL_keysym& keysym) {
	bool ret = StringInputBox::Keyboard(keysym);

	if (userHitEnter) {
		if (CheckNameValid(theInput, true)) {
			MessageWindows(WC_YouClose, 0, 0, all_constant, myID);
			ForceSelect::LoadSide(theInput, true);
		}
	}

	return ret;
}

ChangeCommanderName::ChangeCommanderName():
StringInputBox(maxNameLength, none_constant, 0) {
	title = "What is your name, commander?";

	rect.w = 400;
	rect.h = 100;

	CentreWindow();

	InitRects();
}

bool ChangeCommanderName::Keyboard(SDL_keysym& keysym) {
	bool ret = StringInputBox::Keyboard(keysym);

	if (userHitEnter) {
		if (CheckNameValid(theInput, true)) {
			sides[0].commander = theInput;
			globalSettings.commander = theInput;
		}
	}

	return ret;
}

BasePU::BasePU(int ix, int iy):
PopupMenu(ix, iy, none_constant, 0) {
	MenuItem tempItem;

	tempItem.desc = "Edit group";
	tempItem.choice = WC_SidePU;
	AddItem(tempItem);

	tempItem.desc = "Add new group(s)";
	tempItem.choice = FS_AddGroups;
	AddItem(tempItem);

	tempItem.desc = "Delete group";
	tempItem.choice = FS_DeleteGroup;
	AddItem(tempItem);

	tempItem.desc = "Starting positions";
	tempItem.choice = FS_StartingPositions;
	AddItem(tempItem);

	AddBlankItem();

	tempItem.desc = "Options";
	tempItem.choice = Opt_StandardOptions;
	AddItem(tempItem);
	
	tempItem.desc = "Save and exit";
	tempItem.choice = WC_Quit;
	AddItem(tempItem);
	
	tempItem.desc = "Exit without saving";
	tempItem.choice = FS_ExitNoSave;
	AddItem(tempItem);

	InitRects();
}

bool BasePU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case WC_SidePU:
			myWindows.push_back(GenWindow(WC_SidePU, 0, 0, FS_EditGroup));
			closed = true;
			break;

		case FS_AddGroups:
			if (sides[0].groups.size() < maxGroups) {
				myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "What sort of unit will this group consist of?\nRight click to copy or delete.", 0, 0));
				myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_AddGroupMenu, windowIDs, 0, 0));
			} else
				CreateInfoString("\n\n  You cannot have more than 60 groups on a side");
			closed = true;
			break;

		case FS_DeleteGroup:
			myWindows.push_back(GenWindow(WC_SidePU, 0, 0, FS_DeleteGroup));
			closed = true;
			break;

		case FS_StartingPositions:
			PreBattle::pbState = PBS_Position;
			gsTo = GST_PreBattle;
			break;

		case Opt_StandardOptions:
			myWindows.push_back(GenWindow(rect.x, rect.y, Opt_StandardOptions, 0, 0, 0));
			closed = true;
			break;
			
		case WC_Quit:
			TrySaveAndExit();
			break;
			
		case FS_ExitNoSave:
			myWindows.push_back(GenWindow(0, 0, FS_ExitNoSaveQ, 0, 0, 0));
			closed = true;
			break;
		}
	}

	return false;
}

SideOptions::SideOptions(int ix, int iy, int flags):
DragWindow(0, 0, none_constant, flags) {
	rect.w = 200;
	rect.h = 150;

	rect.x = globalSettings.screenWidth - rect.w - 10;
	rect.y = 10;

	InitBorder();
}

bool SideOptions::MouseD(Uint8 button, Uint16 x, Uint16 y) {
	bool ret = GenWindow_Base::MouseD(button, x, y);

	if (ret == true && button == SDL_BUTTON_RIGHT)
		myWindows.push_back(GenWindow(x, y, FS_SideOptionsPU, 0, 0, 0));

	return ret;
}

void SideOptions::DrawSelf() {
	DragWindow::DrawSelf();

	int x = rect.x + smallBorderSize;
	int y = rect.y + smallBorderSize;
	
	char output[60];

	boldFonts.BlitString(x, y, 0, sides[0].name);
	y += lineGap << 1;

	string outputStr = "Commander: " + sides[0].commander;
	normalFonts.BlitString(x, y, 0, outputStr);
	y += lineGap << 1;

	sprintf(output, "Points value: %d", sides[0].GetPointsValue());
	normalFonts.BlitString(x, y, 0, output);
}

SideOptionsPU::SideOptionsPU(int ix, int iy):
PopupMenu(ix, iy, none_constant, 0) {
	MenuItem tempItem;

	tempItem.desc = "Commander name";
	tempItem.choice = FS_Commander;
	AddItem(tempItem);

	tempItem.desc = "Change saved groups";
	tempItem.choice = FS_ChooseGSaveGroup;
	AddItem(tempItem);

	InitRects();
}

bool SideOptionsPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_Commander:
			myWindows.push_back(GenWindow(0, 0, FS_Commander, 0, 0, 0));
			closed = true;
			break;

		case FS_ChooseGSaveGroup:
			myWindows.push_back(GenWindow(0, 0, FS_WhichSaveGroup, 0, 1, 0));
			closed = true;
			break;
		}
	}

	return false;
}

EditGroup::EditGroup(int ix, int iy, int iMyGroup, int flags):
DragWindow(ix, iy, none_constant, flags), myGroup(iMyGroup) {
	rect.w = 350;
	rect.h = 170;

	InitRects();
}

bool EditGroup::MouseD(Uint8 button, Uint16 x, Uint16 y) {
	bool ret = DragWindow::MouseD(button, x, y);

	if (ret == true && button == SDL_BUTTON_RIGHT)
		myWindows.push_back(GenWindow(x, y, FS_EditGroupPU, myGroup, 0, 0));

	return ret;
}

void EditGroup::DrawSelf() {
	DragWindow::DrawSelf();

	int x = rect.x + smallBorderSize;
	int y = rect.y + smallBorderSize;

	char output[50];
	sprintf(output, "Group %d:", myGroup+1);
	boldFonts.BlitString(x, y, 0, output);

	y += lineGap;

	string outputStr = "Unit name: " + sides[0].groups[myGroup].GetUnitName();
	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap;

	outputStr = "Unit type: " + GetFullTypeName(0, myGroup);
	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap;

	sprintf(output, "Number: %d", sides[0].groups[myGroup].GetUnitsLeft());
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "Points value: %d", sides[0].groups[myGroup].GetPointsValue());
	normalFonts.BlitString(x, y, 0, output);
	y += lineGap << 1;

	int groupNumber = sides[0].groups[myGroup].GetParentCaSh();
	if (groupNumber != -1)
		sprintf(output, "Parent capital ship: Group %d", groupNumber + 1);
	else
		sprintf(output, "Parent capital ship: None");
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "AI script: %s", sides[0].groups[myGroup].GetAIFilename().c_str());
	normalFonts.BlitString(x, y, 0, output);
	
	y += lineGap;
	
   if (sides[0].groups[myGroup].GetType() == UT_CaShUnit) {
		sprintf(output, "Capacity: %d / %d", sides[0].groups[myGroup].GetHowFull(), sides[0].groups[myGroup].GetCapacity());
		normalFonts.BlitString(x, y, 0, output);
	}
}

void EditGroup::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			GroupNumChange(paremOne, paremTwo, myGroup);
			break;
		}
	}
}

AddGroupMenu::AddGroupMenu(int iParentID):
FileListMenu(iParentID) {
	ExpensiveUpdate();
}

void AddGroupMenu::ExpensiveUpdate() {
	ClearItems();

	MenuItem tempItem;

	tempItem.desc = "New capital ship";
	tempItem.choice = FS_NewCaSh;
	AddItem(tempItem);

	tempItem.desc = "New frigate";
	tempItem.choice = FS_NewFr;
	AddItem(tempItem);

	tempItem.desc = "New small ship";
	tempItem.choice = FS_NewSmSh;
	AddItem(tempItem);

	AddBlankItem();

	AddFleetFiles(0, ".dat", FS_AddGroups);

	InitBorder();
}


bool AddGroupMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_NewCaSh:
			myWindows.push_back(GenWindow(FS_NewUnitName, UT_CaShUnit, myID));
			break;

		case FS_NewFr:
			myWindows.push_back(GenWindow(FS_NewUnitName, UT_FrUnit, myID));
			break;

		case FS_NewSmSh:
			myWindows.push_back(GenWindow(FS_NewUnitName, UT_SmShUnit, myID));
			break;

		case FS_AddGroups:
			UnitType iType = RTSUnit::WhatUTIsThis(0, currentSelection.desc);
			CreateNewGroupWins(currentSelection.desc, iType, 0);
			closed = true;
			break;
		}
	}
	else if (currentSelection.choiceType == MCT_RightCursor) {
		switch(currentSelection.choice) {
		case FS_AddGroups:
			myWindows.push_back(GenWindow(x, y, FS_AddGroupPU, currentSelection.desc, myID, 0));
			break;
		}
	}

	return false;
}

NewGroupParentPU::NewGroupParentPU(const string& iName, UnitType iType, int iNumber):
SidePU(0, 0, FS_ChangeParentCap), name(iName), myType(iType), number(iNumber) {}

bool NewGroupParentPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case FS_ChangeParentCap:
			if (sides[mySide].groups[currentSelection.parem].GetType() == UT_CaShUnit) {
				if (sides[mySide].groups[currentSelection.parem].GetHowFull() + number <= sides[0].groups[currentSelection.parem].GetCapacity())
					AddGroups(name, myType, number, CST_None, currentSelection.parem);

				else {
					char output[80];
					sprintf(output, "Cannot fit another %d groups in capital ship %d", number, currentSelection.parem + 1);
					CreateInfoString(output);
				}
			}
			break;
		}
	}

	return false;
}

AddGroupPU::AddGroupPU(int ix, int iy, const string& iUnitName, int iParentID):
PopupMenu(ix, iy, iParentID, 0), unitName(iUnitName) {
	MenuItem tempItem;
	
	tempItem.desc = "Copy unit: " + unitName;
	tempItem.choice = FS_CopyUnit;
	AddItem(tempItem);

	tempItem.desc = "Delete unit: " + unitName;
	tempItem.choice = FS_DeleteUnit;
	AddItem(tempItem);

	InitRects();
}

bool AddGroupPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_CopyUnit:
			myWindows.push_back(GenWindow(WC_CopyBox, unitName, GetFleetDir(0), parentID));
			closed = true;
			break;
			
		case FS_DeleteUnit:
			myWindows.push_back(GenWindow(WC_DeleteBox, unitName, GetFleetDir(0), parentID));
			closed = true;
			break;
		}
	}

	return false;
}

NewUnitName::NewUnitName(UnitType iUnitType, int iParentID):
StringInputBox(maxNameLength, iParentID, 0), unitType(iUnitType) {
	title = "What do you wish to call the new unit type?";

	rect.w = 400;
	rect.h = 100;

	CentreWindow();

	InitRects();
}

bool NewUnitName::Keyboard(SDL_keysym& keysym) {
	bool ret = StringInputBox::Keyboard(keysym);

	if (userHitEnter) {
		if (CheckNameValid(theInput, true)) {
			if (theInput == sides[0].name)
				CreateInfoString("A unit cannot have the same name as your side");
			else {
				CreateNewGroupWins(theInput, unitType, 1);
				MessageWindows(WC_YouClose, 0, 0, parentID, myID);
			}
		}
	}

	return ret;
}

EditGroupPU::EditGroupPU(int ix, int iy, int iMyGroup):
PopupMenu(ix, iy, none_constant, 0), myGroup(iMyGroup) {
	MenuItem tempItem;

	tempItem.desc = "Edit unit";
	tempItem.choice = FS_EditUnit;
	AddItem(tempItem);

	tempItem.desc = "AI script";
	tempItem.choice = FS_ChangeAIScript;
	AddItem(tempItem);

	tempItem.desc = "Change saved groups";
	tempItem.choice = FS_ChooseSaveGroup;
	AddItem(tempItem);

	InitRects();
}

bool EditGroupPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case FS_EditUnit: {
				string unitName = sides[0].groups[myGroup].GetUnitName();
				myWindows.push_back(GenWindow(rect.x, rect.y, FS_EditUnit, myGroup, 0, 0));
				closed = true;
			}
			break;

		case FS_ChangeAIScript:
			myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "Choose an AI script", 0, 0));
			myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_AIScriptMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_ChooseSaveGroup:
			myWindows.push_back(GenWindow(0, 0, FS_WhichSaveGroup, myGroup, 0, 0));
			closed = true;
			break;
		}
	}

	return false;
}

SetAIScriptMenu::SetAIScriptMenu(int iMyGroup, int iParentID):
FileListMenu(iParentID), myGroup(iMyGroup) {
	MenuItem tempItem;
	
	tempItem.desc = "None";
	tempItem.choice = FS_ChangeAIScript;
	AddItem(tempItem);

	AddBlankItem();

	AddFleetFiles(0, ".ai", FS_ChangeAIScript);

	InitBorder();
}

bool SetAIScriptMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_ChangeAIScript:
			if (currentSelection.desc == "None")
				currentSelection.desc = "";
			if (sides[0].aiScripts.find(currentSelection.desc) == sides[0].aiScripts.end()) {
				try {
					sides[0].CreateAIScriptVec(currentSelection.desc);
					sides[0].MakeFunctionLookupTable(currentSelection.desc);
				} catch (runtime_error e) {
					//FIXME we should probably delete the half-loaded script
					ReportOnMinorError(e.what());
					closed = true;
					break;
				}
			}
			
			if (WhichGSharesName(myGroup) != -1)
			   myWindows.push_back(GenWindow(0, 0, FS_ChangeAIScriptPU, currentSelection.desc, myGroup, 0));
			else
			   sides[0].groups[myGroup].ChangeAIScript(currentSelection.desc);
			closed = true;
			break;
		}
	}

	return false;
}

void SetAIScriptMenu::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			GroupNumChange(paremOne, paremTwo, myGroup);
			break;
		}
	}
}

SetAIScriptPU::SetAIScriptPU(const string& iNewScript, int iMyGroup, int iParentID):
Menu_Base(0, 0, iParentID, 0), newScript(iNewScript), myGroup(iMyGroup) {
	MenuItem tempItem;

	tempItem.desc = "Change AI script for just this group or all groups with this unit type?";
	tempItem.choice = WC_Nothing;
	AddItem(tempItem);

	tempItem.desc = "Just this one";
	tempItem.choice = WC_Yes;
	AddItem(tempItem);

	tempItem.desc = "All";
	tempItem.choice = WC_No;
	AddItem(tempItem);

	InitRects();

	CentreWindow();
}

bool SetAIScriptPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case WC_Yes:
			sides[0].groups[myGroup].ChangeAIScript(newScript);
			closed = true;
			break;

		case WC_No:
			ChangeUnitAI(sides[0].groups[myGroup].GetUnitName(), newScript);
			closed = true;
			break;
		}
	}

	return false;
}

void SetAIScriptPU::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			GroupNumChange(paremOne, paremTwo, myGroup);
			break;
		}
	}
}

EditUnit::EditUnit(int ix, int iy, int iMyGroup):
DragWindow(ix, iy, none_constant, 0), myGroup(iMyGroup), myType(sides[0].groups[iMyGroup].GetType()) {
	switch (myType) {
	case UT_SmShUnit:
	case UT_FrUnit:
		rect.w = 400;
		rect.h = FrHeight + 400;
		break;

	case UT_CaShUnit:
		rect.w = HCSWidth + (bigBorderSize << 1);
		rect.h = HCSHeight + 400;
		break;
	}
	
	CentreWindow();

	InitRects();
}

bool EditUnit::MouseD(Uint8 button, Uint16 x, Uint16 y) {
	bool ret = DragWindow::MouseD(button, x, y);

	if (ret == true && button == SDL_BUTTON_RIGHT)
		myWindows.push_back(GenWindow(x, y, FS_EditUnitPU, myGroup, 0, 0));

	return ret;
}

void EditUnit::DrawSelf() {
	DragWindow::DrawSelf();

	int x = rect.x + bigBorderSize;
	int y = rect.y + smallBorderSize;

	char output[50];

	boldFonts.BlitString(x, y, 0, sides[0].groups[myGroup].GetUnitName());

	y += lineGap;

	int picAllowance;

	switch(myType) {
	case UT_CaShUnit:
		picAllowance = HCSHeight;
		break;

	case UT_FrUnit:
	case UT_SmShUnit:
		picAllowance = FrHeight;
		break;
	}

	sides[0].groups[myGroup].DrawUnitPic(x + bigBorderSize, y);

	y += picAllowance + lineGap;

	string outputStr = "Unit type: " + GetFullTypeName(0, myGroup);

	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap << 1;

	outputStr = sides[0].groups[myGroup].GetShieldName();
	outputStr = "Shield: " + outputStr;
	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap << 1;

	outputStr = sides[0].groups[myGroup].GetArmourName();
	outputStr = "Armour: " + outputStr;
	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap << 1;

	outputStr = sides[0].groups[myGroup].GetEngineName();
	outputStr = "Engine: " + outputStr;
	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap << 1;

	outputStr = weaponLookup[sides[0].groups[myGroup].GetSmallType()].name;
	outputStr = "Small weapons: " + outputStr;

	if (myType != UT_SmShUnit) {
		sprintf(output, " * %d", sides[0].groups[myGroup].GetSmallNumber());
		outputStr+= output;
	}

	normalFonts.BlitString(x, y, 0, outputStr);

	y += lineGap << 1;

	outputStr = weaponLookup[sides[0].groups[myGroup].GetBigType()].name;
	outputStr = "Big weapons: " + outputStr;
	if (weaponLookup[sides[0].groups[myGroup].GetBigType()].category == WCAT_Torpedo)
		outputStr += " (25% speed penalty)";
	normalFonts.BlitString(x, y, 0, outputStr);
	y += lineGap << 1;

	if (myType == UT_CaShUnit) {
		sprintf(output, "Capacity: %d", sides[0].groups[myGroup].GetCapacity());
		normalFonts.BlitString(x, y, 0, output);
		y += lineGap << 1;
	}

	if (sides[0].groups[myGroup].GetUnitMaxPoints() != infinite_constant)
		sprintf(output, "Points value: %d / %d", sides[0].groups[myGroup].GetUnitPointsValue(), sides[0].groups[myGroup].GetUnitMaxPoints());
	else
		sprintf(output, "Points value: %d / infinite", sides[0].groups[myGroup].GetUnitPointsValue());
	normalFonts.BlitString(x, y, 0, output);
}

void EditUnit::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
				closed = true;
			break;
		}
	}
}

EditUnitPU::EditUnitPU(int ix, int iy, int iMyGroup):
PopupMenu(ix, iy, none_constant, 0), myGroup(iMyGroup) {
	MenuItem tempItem;

	tempItem.desc = "Change picture";
	tempItem.choice = FS_Picture;
	AddItem(tempItem);

	tempItem.desc = "Small weapons";
	tempItem.choice = FS_SmallWeapons;
	AddItem(tempItem);

	if (sides[0].groups[myGroup].GetType() != UT_CaShUnit) {
		tempItem.desc = "Big weapons";
		tempItem.choice = FS_BigWeapons;
		AddItem(tempItem);

		tempItem.desc = "Engine";

		tempItem.choice = FS_Engine;
		AddItem(tempItem);

		tempItem.desc = "Armour";
		tempItem.choice = FS_Armour;
		AddItem(tempItem);

		tempItem.desc = "Shield";
		tempItem.choice = FS_Shield;
		AddItem(tempItem);
	}
	else {
		tempItem.desc = "Size";
		tempItem.choice = FS_CSType;
		AddItem(tempItem);
	}

	InitRects();
}


bool EditUnitPU::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case FS_Picture:
			myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "Choose a picture", 0, 0));
			myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_PictureMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_SmallWeapons:
			myWindows.push_back(GenWindow(200, 200, FS_WeaponsDW, myGroup, 0, 0));
			myWindows.push_back(GenWindow(200, 200, FS_SmallWeaponsMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_BigWeapons:
			myWindows.push_back(GenWindow(200, 200, FS_WeaponsDW, myGroup, 1, 0));
			myWindows.push_back(GenWindow(200, 200, FS_BigWeaponsMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_Engine:
			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Engine, 0));
			myWindows.push_back(GenWindow(200, 200, FS_EngineMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_Armour:
			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Armour, 0));
			myWindows.push_back(GenWindow(200, 200, FS_ArmourMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_Shield:
			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Shield, 0));
			myWindows.push_back(GenWindow(200, 200, FS_ShieldMenu, myGroup, windowIDs, 0));
			closed = true;
			break;

		case FS_CSType:
			myWindows.push_back(GenWindow(200, 200, FS_CSType, myGroup, 0, 0));
			closed = true;
			break;
		}
	}

	return false;
}

///

SetUnitPicMenu::SetUnitPicMenu(int iMyGroup, int iParentID):
FileListMenu(iParentID), myGroup(iMyGroup) {
	MenuItem tempItem;

	try {
		UnitType uType = sides[0].groups[myGroup].GetType();
		string dir = MakePicDirString(0, RTSUnit_Base::UTypeToPicDir(uType), false);
		if (DoesFileExist(dir))
			AddDirectory(dir, ".png", FS_Picture);
		dir = MakePicDirString(0, RTSUnit_Base::UTypeToPicDir(uType), true);
		AddDirectory(dir, ".png", FS_Picture);
	} catch (boost::filesystem::filesystem_error e) {
		string errorStr = "\n";
		errorStr += e.what();
		CreateInfoString(errorStr);
	}
	
	InitBorder();
}

bool SetUnitPicMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor)
		closed = true;

	return false;
}

bool SetUnitPicMenu::MouseM(Uint8 state, Uint16 x, Uint16 y) {
	bool ret = Menu_Base::MouseM(state, x, y);

	if (currentSelection.choiceType == MCT_Highlight) {
		switch (currentSelection.choice) {
		case FS_Picture:
			string newPic = RTSUnit_Base::UTypeToPicDir(sides[0].groups[myGroup].GetType()) + currentSelection.desc + ".png";
			string oldPic = sides[0].groups[myGroup].GetRealPictureName();

			if (oldPic != newPic)
				ChangeUnitPic(sides[0].groups[myGroup].GetUnitName(), newPic);
			break;
		}
	}

	return ret;
}

void SetUnitPicMenu::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
				closed = true;
			break;
		}
	}
}

////

WeapEquipMenu_Base::WeapEquipMenu_Base(int ix, int iy, int iMyGroup, int iParentID):
Menu_Base(ix, iy, iParentID, 0), myGroup(iMyGroup) {}

WeapEquipMenu_Base::~WeapEquipMenu_Base() {
	MessageWindows(WC_YouClose, 0, 0, parentID, myID);
}

void WeapEquipMenu_Base::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		switch (theMessage) {
			//our group has been deleted
		case FS_GroupNumChange:
			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
				closed = true;
			break;
		}
	}
}

void WeapEquipMenu_Base::InitEquipMenu(WindowChoice first, WindowChoice last) {
	MenuItem tempItem;

	for (WindowChoice i = first; i != last + 1; i = static_cast<WindowChoice>(i + 1)) {
		tempItem.desc = WCToETLookup[i];
		tempItem.choice = equipLookup[tempItem.desc].FSEC;
		AddItem(tempItem);
	}

	InitRects();
}

bool WeapEquipMenu_Base::SharedSwitchOnChoice(void (*ChangeUnitFunction)(const string&, const string&)) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		try {
			ChangeUnitFunction(sides[0].groups[myGroup].GetUnitName(), currentSelection.desc);
		} catch (MinorError e) {
			CreateInfoString(e.what());
		}
		closed = true;
	}

	return false;
}

bool WeapEquipMenu_Base::MouseM(Uint8 state, Uint16 x, Uint16 y) {
	bool ret = Menu_Base::MouseM(state, x, y);

	if (currentSelection.choiceType == MCT_Highlight)
		MessageWindows(currentSelection.choice, 0, 0, parentID, myID);

	return ret;
}

WeaponsDW::WeaponsDW(int ix, int iy, int iMyGroup, int bBig):
DragWindow(ix, iy, none_constant, 0) {
	rect.w = 450;
	rect.h = 200;

	if (bBig)
		weaponChoice = sides[0].groups[iMyGroup].GetBigType();
	else
		weaponChoice = sides[0].groups[iMyGroup].GetSmallType();

	InitRects();
}

void WeaponsDW::DrawSelf() {
	DragWindow::DrawSelf();

	int x = rect.x + 190;
	int y = rect.y;

	char output[50];

	sprintf(output, "Name: %s", (weaponLookup[weaponChoice].name).c_str());
	boldFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "Power: %d", weaponLookup[weaponChoice].power);
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "Range: %d", weaponLookup[weaponChoice].range);
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "Base accuracy: %d %%", weaponLookup[weaponChoice].accuracy);
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	sprintf(output, "Reload: %d ms", weaponLookup[weaponChoice].reload);
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	int startAmmo = weaponLookup[weaponChoice].startAmmo;

	if (startAmmo != 100)
		sprintf(output, "Ammo: %d", weaponLookup[weaponChoice].startAmmo);
	else
		sprintf(output, "Ammo: Infinite");

	normalFonts.BlitString(x, y, 0, output);

	y += lineGap << 1;

	sprintf(output, "Points: %d", weaponLookup[weaponChoice].points);
	normalFonts.BlitString(x, y, 0, output);
}

void WeaponsDW::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	//group deletion should be handled by child menu

	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		if (theMessage >= FS_WT_None - 1 && theMessage <= FS_WT_Torpedo3)
			weaponChoice = WCToWTLookup[theMessage];
	}
}


SmallWeaponsMenu::SmallWeaponsMenu(int ix, int iy, int iMyGroup, int iParentID):
WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
	MenuItem tempItem;

	tempItem.desc = weaponLookup[WT_None].name;
	tempItem.choice = FS_WT_None;
	AddItem(tempItem);

	for (WeaponType i = WT_Twin1; i != WT_Twin3 + 1; i = static_cast<WeaponType>(i + 1)) {
		tempItem.desc = weaponLookup[i].name;
		tempItem.choice = weaponLookup[i].FSWC;
		AddItem(tempItem);
	}

	if (sides[0].groups[myGroup].GetType() != UT_SmShUnit) {
		AddBlankItem();

		for (WeaponType i = WT_BSSmall1; i != WT_BSSmall3 + 1; i = static_cast<WeaponType>(i + 1)) {
			tempItem.desc = weaponLookup[i].name;
			tempItem.choice = weaponLookup[i].FSWC;
			AddItem(tempItem);
		}
	}

	InitRects();
}

bool SmallWeaponsMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	return SharedSwitchOnChoice(ChangeUnitSmallWeapons);
}

BigWeaponsMenu::BigWeaponsMenu(int ix, int iy, int iMyGroup, int iParentID):
WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
	MenuItem tempItem;

	tempItem.desc = weaponLookup[WT_None].name;
	tempItem.choice = weaponLookup[WT_None].FSWC;
	AddItem(tempItem);

	WeaponType first;
	WeaponType last;

	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit) {
		first = WT_Missile1;
		last = WT_Torpedo3;
	} else {
		first = WT_BSLarge1;
		last = WT_BSLarge3;
	}

	for (WeaponType i = first; i != last + 1; i = static_cast<WeaponType>(i + 1)) {
		tempItem.desc = weaponLookup[i].name;
		tempItem.choice = weaponLookup[i].FSWC;
		AddItem(tempItem);
	}

	InitRects();
}

bool BigWeaponsMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	return SharedSwitchOnChoice(ChangeUnitBigWeapons);
}

///

EquipmentDW::EquipmentDW(int ix, int iy, int iMyGroup, int equipType):
DragWindow(ix, iy, none_constant, 0) {
	rect.w = 450;
	rect.h = 200;

	switch (static_cast<WindowChoice>(equipType)) {
	case FS_Engine:
		equipChoice = sides[0].groups[iMyGroup].GetEngineName();
		break;
	case FS_Armour:
		equipChoice = sides[0].groups[iMyGroup].GetArmourName();
		break;
	case FS_Shield:
		equipChoice = sides[0].groups[iMyGroup].GetShieldName();
		break;
	}

	InitRects();
}

void EquipmentDW::DrawSelf() {
	DragWindow::DrawSelf();

	int x = rect.x + 190;
	int y = rect.y;

	char output[50];

	string outputStr = "Name: " + equipChoice;
	boldFonts.BlitString(x, y, 0, outputStr);

	y += lineGap;

	sprintf(output, "Max: %d", equipLookup[equipChoice].max);
	normalFonts.BlitString(x, y, 0, output);

	y += lineGap;

	if (equipLookup[equipChoice].category == EQCAT_SSShield || equipLookup[equipChoice].category == EQCAT_FrShield) {
		sprintf(output, "Recharge interval: %d ms", equipLookup[equipChoice].recharge);
		normalFonts.BlitString(x, y, 0, output);

		y += lineGap;
	}

	y += lineGap;

	sprintf(output, "Points: %d", equipLookup[equipChoice].points);
	normalFonts.BlitString(x, y, 0, output);
}

void EquipmentDW::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
	//group deletion should be handled by child menu

	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);

	if (targetID == all_constant || targetID == myID) {
		if (theMessage >= FS_ET_None - 1 && theMessage <= FS_ET_FrShield3)
			equipChoice = WCToETLookup[theMessage];
	}
}

EngineMenu::EngineMenu(int ix, int iy, int iMyGroup, int iParentID):
WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
		InitEquipMenu(FS_ET_SSEngine1, FS_ET_SSEngine3);
	else
		InitEquipMenu(FS_ET_FrEngine1, FS_ET_FrEngine3);
}

bool EngineMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	return SharedSwitchOnChoice(ChangeUnitEngine);
}

ArmourMenu::ArmourMenu(int ix, int iy, int iMyGroup, int iParentID):
WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
		InitEquipMenu(FS_ET_SSArmour1, FS_ET_SSArmour3);
	else
		InitEquipMenu(FS_ET_FrArmour1, FS_ET_FrArmour3);
}

bool ArmourMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	return SharedSwitchOnChoice(ChangeUnitArmour);
}

ShieldMenu::ShieldMenu(int ix, int iy, int iMyGroup, int iParentID):
WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
	MenuItem tempItem;

	tempItem.desc = weaponLookup[WT_None].name;
	tempItem.choice = weaponLookup[WT_None].FSWC;
	AddItem(tempItem);

	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
		InitEquipMenu(FS_ET_SSShield1, FS_ET_SSShield3);
	else
		InitEquipMenu(FS_ET_FrShield1, FS_ET_FrShield3);
}

bool ShieldMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	return SharedSwitchOnChoice(ChangeUnitShield);
}


////

CSTypeMenu::CSTypeMenu(int ix, int iy, int iMyGroup):
Menu_Base(ix, iy, none_constant, 0), myGroup(iMyGroup) {
	MenuItem tempItem;
	tempItem.rect.h = lineGap << 1;

	tempItem.desc = "New capital ship type?";
	tempItem.choice = WC_Nothing;
	AddItem(tempItem);

	tempItem.rect.h = lineGap;

	tempItem.desc = "Heavy";
	tempItem.choice = FS_HCS;
	AddItem(tempItem);

	tempItem.desc = "Medium";
	tempItem.choice = FS_MCS;
	AddItem(tempItem);

	tempItem.desc = "Light";
	tempItem.choice = FS_LCS;
	AddItem(tempItem);

	InitRects();
}

bool CSTypeMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case FS_HCS:
			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Heavy);
			closed = true;
			break;
		case FS_MCS:
			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Medium);
			closed = true;
			break;
		case FS_LCS:
			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Light);
			closed = true;
			break;
		}
		
		//check that no capital ships are now overly full
		for (int i = 0; i != sides[0].groups.size(); ++i) {
			if (sides[0].groups[i].GetType() == UT_CaShUnit && sides[0].groups[i].GetHowFull() > sides[0].groups[i].GetCapacity()) {
				char output[80];
				sprintf(output, "Capital ship %d now contains too many small ship groups", i + 1);
				CreateInfoString(output);
			}
		}
	}

	//don't let other windows get input until we have got a response
	return true;
}

ForceExitQ::ForceExitQ(const string& error):
Menu_Base(0, 0, none_constant, 0) {
	MenuItem tempItem;
	tempItem.rect.h = lineGap * 5;

	tempItem.desc = "Error saving side:\n" + error + "\n\n" +
	                "Force exit without save?" + '\n';
	tempItem.choice = WC_Nothing;
	AddItem(tempItem);

	tempItem.rect.h = lineGap;

	tempItem.desc = "Yes";
	tempItem.choice = WC_Yes;
	AddItem(tempItem);

	tempItem.desc = "No";
	tempItem.choice = WC_No;
	AddItem(tempItem);

	InitRects();	
	CentreWindow();
}


bool ForceExitQ::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case WC_Yes:
			gsTo = GST_MainMenu;
			break;

		case WC_No:
			closed = true;
			break;
		}
	}

	return false;
}

ExitNoSaveQ::ExitNoSaveQ():
Menu_Base(0, 0, none_constant, 0) {
	MenuItem tempItem;
	tempItem.rect.h = lineGap * 2;

	tempItem.desc = "Exit without saving changes?\n";
	tempItem.choice = WC_Nothing;
	AddItem(tempItem);

	tempItem.rect.h = lineGap;

	tempItem.desc = "Yes";
	tempItem.choice = WC_Yes;
	AddItem(tempItem);

	tempItem.desc = "No";
	tempItem.choice = WC_No;
	AddItem(tempItem);

	InitRects();	
	CentreWindow();
}


bool ExitNoSaveQ::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch(currentSelection.choice) {
		case WC_Yes:
			gsTo = GST_MainMenu;
			break;

		case WC_No:
			closed = true;
			break;
		}
	}

	return false;
}

NewGroupChoicesOK::NewGroupChoicesOK(int ix, int iy, const string& iName, UnitType iMyType, int iIDOne, int iIDTwo, int iParentID):
Menu_Base(ix, iy, iParentID, 0), name(iName), myType(iMyType), sliderOneID(iIDOne), sliderTwoID(iIDTwo) {
	MenuItem tempItem;
	tempItem.desc = "OK";
	tempItem.choice = WC_Yes;
	AddItem(tempItem);

	InitRects();
}

bool NewGroupChoicesOK::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case WC_Yes: {
				int number;

				if (sliderOneID != none_constant) {
					Slider* sliderOne = dynamic_cast<Slider*>(LocateWindow(sliderOneID));
					number = sliderOne->GetSliderVar();
				} else
					number = 1;

				switch (myType) {
				case UT_CaShUnit: {
						int sliderTwoVar = 0;

						if (sliderTwoID != none_constant) {
							Slider* sliderTwo = dynamic_cast<Slider*>(LocateWindow(sliderTwoID));
							sliderTwoVar = sliderTwo->GetSliderVar();
						}

						CapShipType csType = static_cast<CapShipType>(sliderTwoVar);
						AddGroups(name, myType, number, csType, -1);
					}
					break;
				case UT_FrUnit:
					AddGroups(name, myType, number, CST_None, -1);
					break;
				case UT_SmShUnit:
					myWindows.push_back(GenWindow(0, 0, FS_NewGroupParentPU, name, myType, number, 0, 0));
					break;
				}

				MessageWindows(WC_YouClose, 0, 0, parentID, myID);
				closed = true;
			}
			break;
		}
	}

	return false;
}

CapShipTypeSlider::CapShipTypeSlider(int ix, int iy, int iParentID, int flags):
Slider(ix, iy, static_cast<int>(CST_Medium), static_cast<int>(CST_Light), static_cast<int>(CST_Heavy), iParentID, flags) {}

void CapShipTypeSlider::DrawSelf() {
	Slider::DrawSelf();

	CapShipType currentType = static_cast<CapShipType>(sliderVar);
	string typeStr = csTypeToString[currentType];
	typeStr = typeStr.substr(0, typeStr.find(' '));

	//in text
	int x = rect.x + smallBorderSize;
	int y = rect.y + smallBorderSize;
	string output = "Capital ship type: " + typeStr;
	normalFonts.BlitString(x, y, 0, output);
}

WhichSaveGroup::WhichSaveGroup(int iMyGroup, bool globalVar):
PopupMenu(0, 0, none_constant, 0), myGroup(iMyGroup) {
	MenuItem tempItem;
	
	for (int i = 0; i != nAIVars; ++i) {
		char whichStr[60];
		
		if (globalVar) {
			sprintf(whichStr, "$globalg%d:     myside-%d", i, sides[0].saveGroups[i].y + 1);
			tempItem.choice = FS_ChooseGSaveGroup;
		} else {
			sprintf(whichStr, "$g%d:     myside-%d", i, sides[0].groups[myGroup].GetSaveGroup(i).y + 1);
			tempItem.choice = FS_ChooseSaveGroup;
		}
		
		tempItem.desc = whichStr;
		tempItem.parem = i;
		AddItem(tempItem);
	}
	
	InitRects();	
	CentreWindow();
}

bool WhichSaveGroup::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		myWindows.push_back(GenWindow(WC_SidePU, 0, myGroup, currentSelection.choice, currentSelection.parem));
		closed = true;
	}

	return false;
}

DeleteFleet::DeleteFleet(const string& iSideName, int iParentID):
Menu_Base(0, 0, iParentID, 0), sideName(iSideName) {
	MenuItem tempItem;

	tempItem.desc = "Are you sure you wish to delete this fleet?";
	tempItem.choice = WC_Nothing;
	AddItem(tempItem);

	tempItem.desc = "Yes";
	tempItem.choice = WC_Yes;
	AddItem(tempItem);

	tempItem.desc = "No";
	tempItem.choice = WC_No;
	AddItem(tempItem);

	InitRects();
	CentreWindow();
}

bool DeleteFleet::SwitchOnChoice(Uint16 x, Uint16 y) {
	if (currentSelection.choiceType == MCT_LeftCursor) {
		switch (currentSelection.choice) {
		case WC_Yes:
			RemoveDirectory(globalSettings.bdp + "fleets/" + sideName);			
			MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
			closed = true;
			break;

		case WC_No:
			closed = true;
			break;
		}
	}

	return false;
}

CopyFleet::CopyFleet(const string& iSideName, int iParentID):
StringInputBox(maxNameLength, iParentID, 0), sideName(iSideName) {
	title = "What would you like to call the copy?";
	rect.x = 200;
	rect.y = 200;
	rect.w = 400;
	rect.h = 100;

	InitRects();
}

bool CopyFleet::Keyboard(SDL_keysym& keysym) {
	StringInputBox::Keyboard(keysym);

	namespace fs = boost::filesystem;

	if (userHitEnter) {
		if (CheckNameValid(theInput, true)) {
			try {
				fs::path sourcePath(globalSettings.bdp + "fleets/" + sideName);
				fs::path destPath(globalSettings.bdp + "fleets/" + theInput);	
				fs::create_directory(destPath);
				DoCopy(sourcePath, destPath);
				MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
			} catch (fs::filesystem_error e) {
				string errorStr = "\n";
				errorStr += e.what();
				CreateInfoString(errorStr);
			}
		}
	}

	return true;
}

void CopyFleet::DoCopy(boost::filesystem::path sourcePath, boost::filesystem::path destPath) {
	namespace fs = boost::filesystem;	
	fs::directory_iterator directoryEnd; // default construction yields past-the-end
	for (fs::directory_iterator iter(sourcePath); iter != directoryEnd; ++iter) {
		if (is_directory(*iter)) {
			fs::create_directory(destPath.string() + "/" + iter->leaf());
			DoCopy(sourcePath.string() + "/" + iter->leaf(), destPath.string() + "/" + iter->leaf());
			continue;
		}
		string destFile;
		if (iter->leaf() == sideName + ".dat")
			destFile = theInput + ".dat";
		else	
			destFile = iter->leaf();
		
		fs::copy_file(*iter, destPath.string() + "/" + destFile);
	}
}

} //end namespace
