// NFO File EditorDlg.cpp : implementation file
//

#include "stdafx.h"
#include "NFO File Editor.h"
#include "NFO File EditorDlg.h"
#include "NFOPropertiesDlg.h"
#include "NFOAddCycleRuleDlg.h"
#include "NFOErrorDlg.h"
#include "NFOYesNoDlg.h"

#include "..\..\code\buildnum\buildnum.h" // get the current build number

#if !defined(STUFF_STUFF_HPP)
	#include "Stuff\Stuff.hpp"
#endif


#include <GameOS\GameOS.hpp>
#include <MFCPlatform\MFCPlatform.hpp>
#include <Stuff\NotationFile.hpp>

#if 0 // def _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CNFOFileEditorDlg dialog

LRESULT CALLBACK WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	return GameOSWinProc( hWnd, uMsg, wParam, lParam );
}

CNFOFileEditorDlg::CNFOFileEditorDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNFOFileEditorDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CNFOFileEditorDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	
	gosCreated = false;
}

void CNFOFileEditorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNFOFileEditorDlg)
	DDX_Control(pDX, IDC_CYCLE_RESTORE, m_RestoreButton);
	DDX_Control(pDX, IDC_CYCLE_REMOVE_ALL, m_RemoveAllRuleButton);
	DDX_Control(pDX, IDC_CYCLE_SAVE, m_SaveButton);
	DDX_Control(pDX, IDC_CYCLE_MOVE_UP, m_MoveCycleUpButton);
	DDX_Control(pDX, IDC_CYCLE_REMOVE, m_RemoveRuleButton);
	DDX_Control(pDX, IDC_CYCLE_MOVE_DOWN, m_MoveCycleDownButton);
	DDX_Control(pDX, IDC_NFO_REMOVE, m_RemoveNFOButton);
	DDX_Control(pDX, IDC_NFO_ADD, m_AddNFOButton);
	DDX_Control(pDX, IDC_CYCLE_ADD, m_AddRuleButton);
	DDX_Control(pDX, IDC_SERVER_CYCLE_LIST, m_CycleList);
	DDX_Control(pDX, IDC_NFO_PROPERTIES, m_PropertiesButton);
	DDX_Control(pDX, IDC_NFO_MISSIONS, m_MissionList);
	DDX_Control(pDX, IDC_NFO_LIST, m_NFOList);
	//}}AFX_DATA_MAP
}

CNFOFileEditorDlg::~CNFOFileEditorDlg()
{
	if (gosCreated)
	{
		TerminateGameEngine();
		gos_PopCurrentHeap();
		ExitGameOS();

		::DestroyWindow(Window);
		gosCreated = false;
	}
}

BEGIN_MESSAGE_MAP(CNFOFileEditorDlg, CDialog)
	//{{AFX_MSG_MAP(CNFOFileEditorDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_CBN_SELCHANGE(IDC_NFO_MISSIONS, OnSelchangeNFOMissions)
	ON_BN_CLICKED(IDC_NFO_PROPERTIES, OnNFOProperties)
	ON_BN_CLICKED(IDC_CYCLE_ADD, OnCycleAdd)
	ON_BN_CLICKED(IDC_CYCLE_REMOVE, OnCycleRemove)
	ON_BN_CLICKED(IDC_CYCLE_MOVE_DOWN, OnCycleMoveDown)
	ON_BN_CLICKED(IDC_CYCLE_MOVE_UP, OnCycleMoveUp)
	ON_BN_CLICKED(IDC_CYCLE_SAVE, OnCycleSave)
	ON_BN_CLICKED(IDC_NFO_REMOVE, OnNFORemove)
	ON_BN_CLICKED(IDC_NFO_ADD, OnNFOAdd)
	ON_LBN_SELCHANGE(IDC_NFO_LIST, OnSelchangeNFOList)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_SERVER_CYCLE_LIST, OnItemchangedServerCycleList)
	ON_LBN_DBLCLK(IDC_NFO_LIST, OnDblclkNFOList)
	ON_BN_CLICKED(IDC_CYCLE_REMOVE_ALL, OnCycleRemoveAll)
	ON_BN_CLICKED(IDC_CYCLE_RESTORE, OnCycleRestore)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNFOFileEditorDlg message handlers

BOOL CNFOFileEditorDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// This call initializes all strings
	InitStrings();

	// XXX - Take out the check for now.  Ppl might have several directories.
	/*
	// Grab the exe path from the registry
	HKEY key;
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
		"SOFTWARE\\Microsoft\\Microsoft Games\\MechWarrior Vengeance", 
		0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
	{
		CNFOErrorDlg dlg;
		dlg.m_Error = "Your Mechwarrior 4 installation is damaged.  Please re-install Mechwarrior 4.";
		dlg.DoModal();

		CDialog::OnOK();
		return TRUE;
	}
	char path[1024];
	unsigned long path_len = 1024;
	if (RegQueryValueEx(key, "EXE Path", NULL, NULL, (unsigned char*) path, &path_len) != ERROR_SUCCESS)
	{
		CNFOErrorDlg dlg;
		dlg.m_Error = "Your Mechwarrior 4 installation is damaged.  Please re-install Mechwarrior 4.";
		dlg.DoModal();

		CDialog::OnOK();
		return TRUE;
	}
	if (RegCloseKey(key) != ERROR_SUCCESS)
	{
		CNFOErrorDlg dlg;
		dlg.m_Error = "Your Mechwarrior 4 installation is damaged.  Please re-install Mechwarrior 4.";
		dlg.DoModal();

		CDialog::OnOK();
		return TRUE;
	}
	// This is needed in the shipping version so that it doesn't matter where you run
	// the editor it will be able to find the nfo files.
	// However, if you are debugging, please comment this if-block out so that 
	// you can run it in your debug build
	if (SetCurrentDirectory(path) == 0)
	{
		CNFOErrorDlg dlg;
		dlg.m_Error = "Your Mechwarrior 4 installation is damaged.  Please re-install Mechwarrior 4.";
		dlg.DoModal();

		CDialog::OnOK();
		return TRUE;
	}
	*/

	// Check to see if the MW4 installation is damaged
	Stuff::MString missions_path = "resource\\Missions";
	if (GetFileAttributes(missions_path) == -1)
	{
		CNFOErrorDlg dlg;
		dlg.m_Error = "Can't find the resource directory.  Please run this exe in your root Mechwarrior4 directory.";
		dlg.DoModal();

		CDialog::OnOK();
		return TRUE;
	}
	
	Stuff::MString user_missions_path = "resource\\UserMissions";
	if (GetFileAttributes(user_missions_path) == -1)
	{
		if (CreateDirectory(user_missions_path, NULL) == 0)
		{
			CNFOErrorDlg dlg;
			dlg.m_Error = "I/O failure.  The hard disk might be corrupted.";
			dlg.DoModal();

			CDialog::OnOK();
			return TRUE;
		}
	}

	// Inits GOS
	InitGos();

	// Inits NFO List
	m_MissionList.SetCurSel(0);
	GetNFOList();
    m_PropertiesButton.EnableWindow(FALSE); 
	m_RemoveNFOButton.EnableWindow(FALSE);

	// Inits cycle List
	m_CycleList.InsertColumn(0, "NFO File", LVCFMT_LEFT, 80, 1);
	m_CycleList.InsertColumn(1, "Rule Name", LVCFMT_LEFT, 80, 2);
	m_CycleList.InsertColumn(2, "Rule Set", LVCFMT_LEFT, 150, 1);
	m_CycleList.InsertColumn(3, "Team Allowed", LVCFMT_LEFT, 100, 2);
	m_CycleList.InsertColumn(4, "Team Count", LVCFMT_LEFT, 100, 1);
	m_CycleList.SetExtendedStyle(LVS_EX_FULLROWSELECT);
	LoadCycle();

	::ShowWindow(Window,SW_HIDE);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CNFOFileEditorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CNFOFileEditorDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CNFOFileEditorDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


// Most used strings are stored here for easy localization
void CNFOFileEditorDlg::InitStrings()
{
	m_szScenarioName[0] = "Stock Destruction";
	m_szScenarioName[1] = "Stock Team Destruction";
	m_szScenarioName[2] = "Stock Attrition";
	m_szScenarioName[3] = "Stock Team Attrition";
	m_szScenarioName[4] = "Stock Capture the Flag";
	m_szScenarioName[5] = "Stock King of the Hill";
	m_szScenarioName[6] = "Stock Team King of the Hill";
	m_szScenarioName[7] = "Stock Territories";
	m_szScenarioName[8] = "Stock Steal the Beacon";
	m_szScenarioName[9] = "Stock Capture Base";
	m_szScenarioName[10] = "Stock Destroy Objective";
	m_szScenarioName[11] = "Stock Escort";
	m_szScenarioName[12] = "Stock Master Trial";
	m_szScenarioName[13] = "Stock Siege Assault";
	m_szScenarioName[14] = "Stock Campaign";
	m_szScenarioName[15] = "Custom Destruction";
	m_szScenarioName[16] = "Custom Team Destruction";
	m_szScenarioName[17] = "Custom Attrition";
	m_szScenarioName[18] = "Custom Team Attrition";
	m_szScenarioName[19] = "Custom Capture the Flag";
	m_szScenarioName[20] = "Custom King of the Hill";
	m_szScenarioName[21] = "Custom Team King of the Hill";
	m_szScenarioName[22] = "Custom Territories";
	m_szScenarioName[23] = "Custom Steal the Beacon";
	m_szScenarioName[24] = "Custom Capture Base";
	m_szScenarioName[25] = "Custom Destroy Objective";
	m_szScenarioName[26] = "Custom Escort";
	m_szScenarioName[27] = "Custom Master Trial";
	m_szScenarioName[28] = "Custom Siege Assault";
	m_szScenarioName[29] = "Custom Campaign";
	m_szScenarioName[30] = "Custom Undefined";

	m_szScenarioGameTypeName[0] = "$(StockDestruction)";
	m_szScenarioGameTypeName[1] = "$(StockTeamDestruction)";
	m_szScenarioGameTypeName[2] = "$(StockAttrition)";
	m_szScenarioGameTypeName[3] = "$(StockTeamAttrition)";
	m_szScenarioGameTypeName[4] = "$(StockCaptureTheFlag)";
	m_szScenarioGameTypeName[5] = "$(StockKingOfTheHill)";
	m_szScenarioGameTypeName[6] = "$(StockTeamKingOfTheHill)";
	m_szScenarioGameTypeName[7] = "$(StockTerritories)";
	m_szScenarioGameTypeName[8] = "$(StockStealTheBacon)";
	m_szScenarioGameTypeName[9] = "$(StockCaptureBase)";
	m_szScenarioGameTypeName[10] = "$(StockDestroyObjective)";
	m_szScenarioGameTypeName[11] = "$(StockEscort)";
	m_szScenarioGameTypeName[12] = "$(StockMasterTrial)";
	m_szScenarioGameTypeName[13] = "$(StockSiegeAssault)";
	m_szScenarioGameTypeName[14] = "$(StockCampaign)";
	m_szScenarioGameTypeName[15] = "$(CustomDestruction)";
	m_szScenarioGameTypeName[16] = "$(CustomTeamDestruction)";
	m_szScenarioGameTypeName[17] = "$(CustomAttrition)";
	m_szScenarioGameTypeName[18] = "$(CustomTeamAttrition)";
	m_szScenarioGameTypeName[19] = "$(CustomCaptureTheFlag)";
	m_szScenarioGameTypeName[20] = "$(CustomKingOfTheHill)";
	m_szScenarioGameTypeName[21] = "$(CustomTeamKingOfTheHill)";
	m_szScenarioGameTypeName[22] = "$(CustomTerritories)";
	m_szScenarioGameTypeName[23] = "$(CustomStealTheBacon)";
	m_szScenarioGameTypeName[24] = "$(CustomCaptureBase)";
	m_szScenarioGameTypeName[25] = "$(CustomDestroyObjective)";
	m_szScenarioGameTypeName[26] = "$(CustomEscort)";
	m_szScenarioGameTypeName[27] = "$(CustomMasterTrial)";
	m_szScenarioGameTypeName[28] = "$(CustomSiegeAssault)";
	m_szScenarioGameTypeName[29] = "$(CustomCampaign)";
	m_szScenarioGameTypeName[30] = "$(CustomUndefined)";

	m_szScenarioText[0] = "resource\\missions\\des.txt";
	m_szScenarioText[1] = "resource\\missions\\des.txt";
	m_szScenarioText[2] = "resource\\missions\\att.txt";
	m_szScenarioText[3] = "resource\\missions\\att.txt";
	m_szScenarioText[4] = "resource\\missions\\ctf.txt";
	m_szScenarioText[5] = "resource\\missions\\koth.txt";
	m_szScenarioText[6] = "resource\\missions\\koth.txt";
	m_szScenarioText[7] = "";
	m_szScenarioText[8] = "resource\\missions\\stb.txt";
	m_szScenarioText[9] = "";
	m_szScenarioText[10] = "";
	m_szScenarioText[11] = "resource\\missions\\escort.txt";
	m_szScenarioText[12] = "resource\\missions\\mt.txt";
	m_szScenarioText[13] = "resource\\missions\\siege.txt";
	m_szScenarioText[14] = "";
	m_szScenarioText[15] = "";
	m_szScenarioText[16] = "";
	m_szScenarioText[17] = "";
	m_szScenarioText[18] = "";
	m_szScenarioText[19] = "";
	m_szScenarioText[20] = "";
	m_szScenarioText[21] = "";
	m_szScenarioText[22] = "";
	m_szScenarioText[23] = "";
	m_szScenarioText[24] = "";
	m_szScenarioText[25] = "";
	m_szScenarioText[26] = "";
	m_szScenarioText[27] = "resource\\missions\\mt.txt";
	m_szScenarioText[28] = "resource\\missions\\siege.txt";
	m_szScenarioText[29] = "";
	m_szScenarioText[30] = "";

	m_iTeam[0] = 0;
	m_iTeam[1] = 1;
	m_iTeam[2] = 0;
	m_iTeam[3] = 1;
	m_iTeam[4] = 1;
	m_iTeam[5] = 0;
	m_iTeam[6] = 1;
	m_iTeam[7] = 1;
	m_iTeam[8] = 0;
	m_iTeam[9] = 1;
	m_iTeam[10] = 1;
	m_iTeam[11] = 1;
	m_iTeam[12] = 1;
	m_iTeam[13] = 1;
	m_iTeam[14] = 0;
	m_iTeam[15] = 0;
	m_iTeam[16] = 1;
	m_iTeam[17] = 0;
	m_iTeam[18] = 1;
	m_iTeam[19] = 1;
	m_iTeam[20] = 0;
	m_iTeam[21] = 1;
	m_iTeam[22] = 1;
	m_iTeam[23] = 0;
	m_iTeam[24] = 1;
	m_iTeam[25] = 1;
	m_iTeam[26] = 1;
	m_iTeam[27] = 1;
	m_iTeam[28] = 1;
	m_iTeam[29] = 0;
	m_iTeam[30] = 1;

	m_bBots[0] = TRUE;
	m_bBots[1] = TRUE;
	m_bBots[2] = TRUE;
	m_bBots[3] = TRUE;
	m_bBots[4] = FALSE;
	m_bBots[5] = FALSE;
	m_bBots[6] = FALSE;
	m_bBots[7] = FALSE;
	m_bBots[8] = FALSE;
	m_bBots[9] = FALSE;
	m_bBots[10] = FALSE;
	m_bBots[11] = FALSE;
	m_bBots[12] = FALSE;
	m_bBots[13] = FALSE;
	m_bBots[14] = FALSE;
	m_bBots[15] = TRUE;
	m_bBots[16] = TRUE;
	m_bBots[17] = TRUE;
	m_bBots[18] = TRUE;
	m_bBots[19] = TRUE;
	m_bBots[20] = TRUE;
	m_bBots[21] = TRUE;
	m_bBots[22] = TRUE;
	m_bBots[23] = TRUE;
	m_bBots[24] = TRUE;
	m_bBots[25] = TRUE;
	m_bBots[26] = TRUE;
	m_bBots[27] = FALSE;
	m_bBots[28] = TRUE;
	m_bBots[29] = TRUE;
	m_bBots[30] = TRUE;

	m_szYesNo[0] = "No";
	m_szYesNo[1] = "Yes";

	m_szTOD[0] = "Day";
	m_szTOD[1] = "Night";

	m_szRadar[0] = "Normal";
	m_szRadar[1] = "Team Only";
	m_szRadar[2] = "No Radar";

	m_szDefault = "Default";
	m_szNone = "None";
}

// Initialize GOS so that we can use the notation file system
void CNFOFileEditorDlg::InitGos()
{
	if (!gosCreated)
	{
		HINSTANCE	hInstance;
		hInstance = AfxGetResourceHandle();
		
		WNDCLASS	wc;
		wc.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
		wc.lpfnWndProc = (WNDPROC) WinProc;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hInstance = hInstance;
		wc.hIcon = NULL;
		wc.hCursor = LoadCursor( NULL, IDC_ARROW );
		wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
		wc.lpszMenuName = "Test MFC";
		wc.lpszClassName = "Test MFC";
		RegisterClass(&wc);

		RECT WindowRect;
		WindowRect.left=0;
		WindowRect.top=0;
		WindowRect.right=640;
		WindowRect.bottom=480;
		AdjustWindowRect( &WindowRect,WS_OVERLAPPED,0 );

		Window = CreateWindow( "Test MFC", "Test MFC",
								WS_OVERLAPPEDWINDOW,
								CW_USEDEFAULT, CW_USEDEFAULT,
								WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top,
								NULL, NULL, hInstance, NULL);

		//::ShowWindow( Window, SW_SHOWDEFAULT );

		//
		// Init GameOS with window created
		//
		InitGameOS( hInstance, Window, NULL );

		gosCreated = true;
	}
}


// Load the NFOs in the given directory
void CNFOFileEditorDlg::GetNFOList()
{
	// Oh we need to clear the list first
	m_NFOList.ResetContent();

	// choose the directory we need
	Stuff::MString missions_path;
	int mission = m_MissionList.GetCurSel();
	switch (mission)
	{
	case 0:
		missions_path = "resource\\Missions\\*.nfo";
		break;
	case 1:
		missions_path = "resource\\UserMissions\\*.nfo";
		break;
	default:
		ASSERT(!"Mission selection is invalid!");
		return;
	}

	// now grab all the files in that directory
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, false);	
	Check_Object(resource_directory);
	Register_Object(resource_directory);
	Stuff::MString temp_dir_string;
	while((char *)(temp_dir_string = resource_directory->GetCurrentFileName()) != NULL)
	{
		m_NFOList.AddString(temp_dir_string);
		resource_directory->AdvanceCurrentFile();
	}
	Unregister_Object(resource_directory);
	delete resource_directory;

	if (m_NFOList.GetCount() == 0)
		m_AddRuleButton.EnableWindow(FALSE);
	else
		m_AddRuleButton.EnableWindow(TRUE);
}

// Load the servercycle.txt
void CNFOFileEditorDlg::LoadCycle()
{
	// Clear the cycle list first
	m_CycleList.DeleteAllItems();

	// See if we can find servercycle.txt.  If not then create one
	if (GetFileAttributes("servercycle.txt") == -1)
	{
		HANDLE hdl = CreateFile("servercycle.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hdl == INVALID_HANDLE_VALUE)
		{
			CNFOErrorDlg dlg;
			dlg.m_Error = "I/O failure.  The hard disk might be corrupted.";
			dlg.DoModal();

			CDialog::OnOK();
			return;
		}

		int value = CloseHandle(hdl);
		ASSERT(value != 0);
		if (value == 0)
		{
			CNFOErrorDlg dlg;
			dlg.m_Error = "I/O failure.  The hard disk might be corrupted.";
			dlg.DoModal();

			CDialog::OnOK();
			return;
		}
	}

	// grab the servercycle.txt
	Stuff::MString cycle_path = "servercycle.txt";
	Stuff::NotationFile notefile(cycle_path, Stuff::NotationFile::Standard, TRUE);	
	Stuff::Page *page = notefile.FindPage("cycle");
	if (page != NULL)
	{
		Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
		Stuff::Note *note;
		int map_count = 0;
		while ((note = notes->ReadAndNext()) != NULL)
		{
			Stuff::MString current_name = note->GetName();
			if (current_name == "map")
			{
				const char *temp;
				note->GetEntry(&temp);

				Stuff::MString nfo_text = temp;
				Stuff::MString scenario_name;
				Stuff::MString scenario_text;

				char *pointer = strstr((char*)nfo_text, "::" );
				if (pointer && pointer != (char*)nfo_text)
				{
					*pointer = '\0';
					pointer += 2;
					scenario_name = pointer;

					// first search the missions directory
					Stuff::MString nfo_name;
					nfo_name = "resource\\Missions\\";
					nfo_name += nfo_text;
					if (GetFileAttributes(nfo_name) == -1)
					{
						// search the user missions directory
						nfo_name = "resource\\UserMissions\\";
						nfo_name += nfo_text;

						if (GetFileAttributes(nfo_name) == -1)
						{
							// no file associated, so let's not include this rule and continue
							continue;
						}
					}
	
					// Grab the scenarios
					if (LoadScenario(nfo_name, nfo_text, scenario_name, map_count) == TRUE)
						map_count++;
				}
			}
		}
	}
	
	m_bSaved = TRUE;
	m_SaveButton.EnableWindow(FALSE);
	
	// disable buttons that should be unavailable
	m_RemoveRuleButton.EnableWindow(FALSE);
	m_MoveCycleUpButton.EnableWindow(FALSE);
	m_MoveCycleDownButton.EnableWindow(FALSE);
	
	if (m_CycleList.GetItemCount() == 0)
		m_RemoveAllRuleButton.EnableWindow(FALSE);
	else
		m_RemoveAllRuleButton.EnableWindow(TRUE);
}

BOOL CNFOFileEditorDlg::LoadScenario(char* nfo_name, char* nfo_text, char* scenario_name, int count)
{
	Stuff::NotationFile notefile(nfo_name, Stuff::NotationFile::Standard, true);

	// See if we have a ruleset tab and if so, collect the available rules
	BOOL bTypeExists = FALSE;
	BOOL bTypeAvailable[GameTypeCount];
	for (int j = 0; j < GameTypeCount; j++)
	{
		bTypeAvailable[j] = FALSE;
	}
	INT iMaxTeam[GameTypeCount] = 
		{ 0, 8, 0, 8, 2, 0, 8, 8, 0, 8, 0, 4, 0,
		  0, 8, 0, 8, 2, 0, 8, 8, 0, 8, 0, 4, 0  };
	Stuff::Page* page = notefile.FindPage("ruleset");
	if (page != NULL)
	{
		Stuff::ChainIteratorOf<Stuff::Note*> *note_iterator = page->MakeNoteIterator();

		Stuff::Note *note;		
		int rule_set = -1;
		int max_team = -1;
		while ((note = note_iterator->ReadAndNext()) != NULL)
		{
			if (_stricmp(note->GetName(), "type") == 0)
			{
				note->GetEntry(&rule_set);
				
				if ((rule_set > -1) && (rule_set < GameTypeCount))
				{
					bTypeAvailable[rule_set] = TRUE;
					bTypeExists = TRUE;
				}
			}
			else
			{
				if ((rule_set > -1) && (rule_set < GameTypeCount))
				{
					if (_stricmp(note->GetName(), "team") == 0)
					{
						note->GetEntry(&max_team);
						if ((max_team > -1) && (max_team < 9))
							iMaxTeam[rule_set] = max_team;
					}
				}
			}
		}
	}

	page = notefile.FindPage("scenarios");
	if (page != NULL)
	{
		char intbuf[256];
		Stuff::Note *note = page->FindNote(scenario_name);
		if (note != NULL)
		{
			Stuff::NotationFile scenario_file;
			note->GetEntry(&scenario_file);
								
			Stuff::Page *server_page = scenario_file.FindPage("server");
			if (server_page)
			{
				int rule_set = -1;
				int team_allowed = -1;
				int team_count = -1;

				server_page->GetEntry("ruleset",&rule_set);
				server_page->GetEntry("teamAllowed",&team_allowed);
				server_page->GetEntry("teamCount",&team_count);

				if ((rule_set > -1) && (rule_set < GameTypeCount))
				{
					if ((bTypeExists != TRUE) || (bTypeAvailable[rule_set] == TRUE))
					{
						// invalid team allowed or team count
						if ((team_allowed < -1) || (team_allowed > 1) ||
							(team_count < -1) || (team_count > 9))
							return FALSE;

						// if the scenario doesn't have teamallowed or teamcount specified, we
						// should use default
						if (team_allowed == -1)
							team_allowed = m_iTeam[rule_set];
						if (team_allowed)
						{	
							if ((team_count == -1) || (team_count > iMaxTeam[rule_set]))
								team_count = iMaxTeam[rule_set];
						}
						else
							team_count = 0;

						m_CycleList.InsertItem(count, nfo_text, 0);
						m_CycleList.SetItemText(count, 1, scenario_name);
						m_CycleList.SetItemText(count, 2, m_szScenarioName[rule_set]);	
						m_CycleList.SetItemText(count, 3, m_szYesNo[team_allowed]);	
						m_CycleList.SetItemText(count, 4, _itoa(team_count, intbuf, 10));
						return TRUE;
					}
				}
			}
		}		
	}

	return FALSE;
}

// Save servercycle.txt
void CNFOFileEditorDlg::SaveCycle()
{
	// Save the server cycle list
	Stuff::MString cycle_path = "servercycle.txt";
	Stuff::NotationFile notefile(cycle_path);	
	Stuff::Page *page = notefile.SetPage("cycle");
	if (page != NULL)
	{
		page->DeleteAllNotes();

		int count = m_CycleList.GetItemCount();
		ASSERT(count > 0);

		char file[256];
		char map[256];
		for (int i = 0; i < count; i++)
		{
			m_CycleList.GetItemText(i, 0, file, 256);
			m_CycleList.GetItemText(i, 1, map, 256);
			strcat(file, "::");
			strcat(file, map);
			page->AppendEntry("map", file);
		}
	}
	
	notefile.Save();
	
	m_bSaved = TRUE;
	m_SaveButton.EnableWindow(FALSE);
}

// When user selects a new NFO mission directory, load the NFO list
// and disable some buttons
void CNFOFileEditorDlg::OnSelchangeNFOMissions() 
{
	GetNFOList();
    m_PropertiesButton.EnableWindow(FALSE); 
	m_RemoveNFOButton.EnableWindow(FALSE);
}

// See the property of a NFO file
void CNFOFileEditorDlg::OnNFOProperties() 
{
	int curSel = m_NFOList.GetCurSel();
	ASSERT(curSel != LB_ERR);

	m_bEditNFO = TRUE;

	CNFOPropertiesDlg dlg;
	int value = dlg.DoModal();
	ASSERT(value != -1);
}

// Add a server cycle rule 
void CNFOFileEditorDlg::OnCycleAdd() 
{
	CNFOAddCycleRuleDlg dlg;
	int value = dlg.DoModal();
	ASSERT(value != -1);

	if (value == 1)
	{
		if (m_CycleList.GetItemCount() > 0)
		{
			m_SaveButton.EnableWindow(TRUE);
			m_RemoveAllRuleButton.EnableWindow(TRUE);
		}
	
		m_bSaved = FALSE;
	}	
}

// Remove a server cycle rule
void CNFOFileEditorDlg::OnCycleRemove() 
{
	int curSel = m_CycleList.GetSelectionMark();
	ASSERT(curSel != LB_ERR);

	int value = m_CycleList.DeleteItem(curSel);
	ASSERT(value == TRUE);

	// clear the selection mark
	m_CycleList.SetSelectionMark(-1);
	
	// disable the appropriate buttons
	m_MoveCycleUpButton.EnableWindow(FALSE);
	m_MoveCycleDownButton.EnableWindow(FALSE);
	m_RemoveRuleButton.EnableWindow(FALSE);

	// can't save if no cycle rule is present
	if (m_CycleList.GetItemCount() == 0)
	{
		m_SaveButton.EnableWindow(FALSE);
		m_RemoveAllRuleButton.EnableWindow(FALSE);
	}
	else
	{
		m_SaveButton.EnableWindow(TRUE);
		m_RemoveAllRuleButton.EnableWindow(TRUE);
	}

	m_bSaved = FALSE;
}

void CNFOFileEditorDlg::OnCycleMoveDown() 
{
	int curSel = m_CycleList.GetSelectionMark();
	ASSERT(curSel != LB_ERR);

	int nColumnCount = m_CycleList.GetHeaderCtrl()->GetItemCount();
	char bufUp[256];
	char bufDown[256];
	for (int i = 0; i < nColumnCount; i++)
	{
		m_CycleList.GetItemText(curSel, i, bufUp, 256);
		m_CycleList.GetItemText(curSel + 1, i, bufDown, 256);
		m_CycleList.SetItemText(curSel, i, bufDown);
		m_CycleList.SetItemText(curSel + 1, i, bufUp);
	}

	m_CycleList.SetSelectionMark(curSel + 1);	
	m_CycleList.SetItemState(curSel + 1, LVIS_FOCUSED | LVIS_SELECTED, 255);
	
	// if we are at the last one, disable the move down button
	m_MoveCycleUpButton.EnableWindow(TRUE);
	if (curSel + 1 == m_CycleList.GetItemCount() - 1)
		m_MoveCycleDownButton.EnableWindow(FALSE);

	m_bSaved = FALSE;
	m_SaveButton.EnableWindow(TRUE);
}

void CNFOFileEditorDlg::OnCycleMoveUp() 
{
	int curSel = m_CycleList.GetSelectionMark();
	ASSERT(curSel != LB_ERR);

	int nColumnCount = m_CycleList.GetHeaderCtrl()->GetItemCount();
	char bufUp[256];
	char bufDown[256];
	for (int i = 0; i < nColumnCount; i++)
	{
		m_CycleList.GetItemText(curSel - 1, i, bufUp, 256);
		m_CycleList.GetItemText(curSel, i, bufDown, 256);
		m_CycleList.SetItemText(curSel - 1, i, bufDown);
		m_CycleList.SetItemText(curSel, i, bufUp);
	}

	m_CycleList.SetSelectionMark(curSel - 1);
	m_CycleList.SetItemState(curSel - 1, LVIS_FOCUSED | LVIS_SELECTED, 255);

	// if we are at the first one, diable the move up button
	m_MoveCycleDownButton.EnableWindow(TRUE);
	if (curSel - 1 == 0)
		m_MoveCycleUpButton.EnableWindow(FALSE);

	m_bSaved = FALSE;
	m_SaveButton.EnableWindow(TRUE);
}

void CNFOFileEditorDlg::OnCycleSave() 
{
	SaveCycle();	
	
	CNFOErrorDlg dlg;
	dlg.m_Error = "Server Cycle List Saved.";
	dlg.DoModal();
}

void CNFOFileEditorDlg::OnNFORemove() 
{
	// NOT USED for now
	/*
	int curSel = m_NFOList.GetCurSel();
	ASSERT(curSel != LB_ERR);
	
	// Get the name of the NFO
	char filename[256];
	int value = m_NFOList.GetText(curSel, filename);
	ASSERT(value != LB_ERR);
	Stuff::MString missions_path;
	int mission = m_MissionList.GetCurSel();
	switch (mission)
	{
	case 0: // missions
		missions_path = "resource\\Missions\\";
		break;
	case 1:
		missions_path = "resource\\UserMissions\\";
		break;
	}
	missions_path += filename;

	// Go ahead and delete the file
	value = DeleteFile(missions_path);
	ASSERT(value != 0);
	if (value == 0)
		return;

	m_NFOList.DeleteString(curSel);
	*/
}

void CNFOFileEditorDlg::OnNFOAdd() 
{
	// NOT USED for now
	/*
	m_bEditNFO = FALSE;	

	CNFOPropertiesDlg dlg;
	int value = dlg.DoModal();
	ASSERT(value != -1);
	
	GetNFOList();
	*/
}

void CNFOFileEditorDlg::OnSelchangeNFOList() 
{
	// Make sure that these two buttons are on if there is a NFO selection
    m_PropertiesButton.EnableWindow(TRUE); 
	m_RemoveNFOButton.EnableWindow(TRUE);
}

void CNFOFileEditorDlg::OnItemchangedServerCycleList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	int nSelected = pNMListView->iItem;

	// Always enable the remove button
	m_RemoveRuleButton.EnableWindow(TRUE);

	if (m_CycleList.GetItemCount() > 1)
	{
		// if we have more than one cycle rule, then enable appripriate buttons
		if (nSelected == 0)
			m_MoveCycleUpButton.EnableWindow(FALSE);
		else
			m_MoveCycleUpButton.EnableWindow(TRUE);
		if (nSelected == m_CycleList.GetItemCount() - 1)
			m_MoveCycleDownButton.EnableWindow(FALSE);
		else
			m_MoveCycleDownButton.EnableWindow(TRUE);
	}
	else
	{
		// otherwise disable both move buttons
		m_MoveCycleUpButton.EnableWindow(FALSE);
		m_MoveCycleDownButton.EnableWindow(FALSE);
	}
	
	*pResult = 0;
}

void CNFOFileEditorDlg::OnDblclkNFOList() 
{
	OnNFOProperties();
}

void CNFOFileEditorDlg::OnCycleRemoveAll() 
{
	int count = m_CycleList.GetItemCount();
	ASSERT(count != LB_ERR);

	for (int i = 0; i < count; i++)
	{
		int value = m_CycleList.DeleteItem(0);
		ASSERT(value == TRUE);
	}

	// clear the selection mark
	m_CycleList.SetSelectionMark(-1);
	
	// disable the appropriate buttons
	m_MoveCycleUpButton.EnableWindow(FALSE);
	m_MoveCycleDownButton.EnableWindow(FALSE);
	m_RemoveRuleButton.EnableWindow(FALSE);
	m_RemoveAllRuleButton.EnableWindow(FALSE);
	m_SaveButton.EnableWindow(FALSE);

	m_bSaved = FALSE;
}

void CNFOFileEditorDlg::OnOK() 
{	
	if (m_bSaved != TRUE)
	{
		if (m_CycleList.GetItemCount() > 0)
		{
			CNFOYesNoDlg dlg;
			dlg.m_Question = "Do you want to save the Server Cycle List?";
			int value = dlg.DoModal();
			ASSERT(value != -1);
			if (value == 1)
			{
				SaveCycle();
			}
		}
		else
		{
			CNFOErrorDlg dlg;
			dlg.m_Error = "The current Server Cycle List is empty.  Servercycle.txt will stay at its last saved state.";
			dlg.DoModal();
		}
	}
	
	CDialog::OnOK();
}

void CNFOFileEditorDlg::OnCycleRestore() 
{
	LoadCycle();

	CNFOErrorDlg dlg;
	dlg.m_Error = "Server Cycle List Restored.";
	dlg.DoModal();
}
