// EditBatchFile.cpp : implementation file
//

#include "stdafx.h"
#ifdef STRICT							// Already defined by stdafx,
#undef STRICT							// so we avoid warning linking msg
#endif
#ifdef _MBCS							// The same as above
#undef _MBCS
#endif

#include "EditBatchFile.h"
#include <GameOS\ToolOS.hpp>

//#include "brb.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString g_szbrowsepath;
static int CALLBACK BrowseCallbackProc1(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
	RECT rect;
	//
	//Center the browse dialog on the screen...
	//
	switch (uMsg)
	{
	case BFFM_INITIALIZED:
		{
			SendMessage(hWnd,BFFM_SETSELECTION,TRUE,(LPARAM)(LPCTSTR)g_szbrowsepath);
	
			if (GetWindowRect(hWnd, &rect))
			{
				SetWindowPos(hWnd, 
							 HWND_TOP,
							 (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) >> 1,
							 (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) >> 1,
							 0,
							 0,
							 SWP_NOSIZE);
			}
		}
	}
	return 0;
}

CString BrowseDirectory(const char *strCurrent,CWnd *pWnd)
{
	CString str;
	TCHAR        szBuffer[MAX_PATH];
	LPITEMIDLIST pidlBrowse,pidlRoot;
	BROWSEINFO   bi;

	LPMALLOC lpMalloc;
	SHGetMalloc(&lpMalloc);
	ASSERT(lpMalloc);
	bi.hwndOwner = pWnd->GetSafeHwnd();
	// Get the ID for the "My Computer" root folder
	SHGetSpecialFolderLocation(pWnd->GetSafeHwnd(),CSIDL_DRIVES | CSIDL_NETWORK,&pidlRoot);

	bi.pidlRoot  = pidlRoot;
	bi.pszDisplayName = szBuffer;

	// Localize the descriptive text
	bi.lpszTitle = "Select a Building, Mech, or Vehicle model root folder.  This contains the LODs, and skeleton.";

	// BIF_EDITBOX and BIF_VALIDATE are for versions 4.71 and later, they
	// might be ignored by older versions
	bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;// | BIF_EDITBOX;// | BIF_USENEWUI;// | BIF_VALIDATE;
	bi.lParam = (LPARAM)pWnd;
	bi.iImage = NULL;
	bi.lpfn = BrowseCallbackProc1;
	bi.lParam = (LPARAM)strCurrent;
	g_szbrowsepath = strCurrent;
	//
	//Call the Windows shell folder browsing routine...
	//
	pidlBrowse = SHBrowseForFolder(&bi);
	if (NULL != pidlBrowse)
	{
		if (SHGetPathFromIDList(pidlBrowse, szBuffer))
		{
			if ('\\' == szBuffer[lstrlen(szBuffer)-1])
				szBuffer[lstrlen(szBuffer)-1] = '\0';
			str = CString(szBuffer);
		}
		else
			str = "";
		//
		//Free up shell memory used...
		//
		lpMalloc->Free(pidlBrowse);
	}
	else
		str = "";
	lpMalloc->Free(pidlRoot);
	lpMalloc->Release();
	return str;
}

/////////////////////////////////////////////////////////////////////////////
// CEditBatchFile dialog


CEditBatchFile::CEditBatchFile(CString batchfile,Interface *i,CWnd* pParent /*=NULL*/)
	: CDialog(CEditBatchFile::IDD, pParent)
{
	m_strFileName = batchfile;
	if (::gos_FileReadOnly(batchfile))
		::gos_FileSetReadWrite(batchfile);

	m_pNotefile = new NotationFile(batchfile);
	Register_Object(m_pNotefile);
	ip = i;
	//{{AFX_DATA_INIT(CEditBatchFile)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CEditBatchFile::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CEditBatchFile)
	DDX_Control(pDX, IDC_LIST1, m_list);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CEditBatchFile, CDialog)
	//{{AFX_MSG_MAP(CEditBatchFile)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_MODIFY, OnModify)
	ON_BN_CLICKED(IDC_ADD, OnAdd)
	ON_BN_CLICKED(IDC_REMOVE, OnRemove)
	ON_BN_CLICKED(IDC_EXPORT, OnExport)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEditBatchFile message handlers

BOOL CEditBatchFile::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	m_list.ResetContent();
	NotationFile::PageIterator *pages = m_pNotefile->MakePageIterator();
	Check_Object(pages);
	Page *page;
	while (page = pages->ReadAndNext())
	{
		CString name = page->GetName();
		int index = m_list.AddString(name);
		//m_list.SetItemData(index,(DWORD)page);
	}
	delete pages;
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CEditBatchFile::OnDestroy() 
{
	CDialog::OnDestroy();
	if (m_pNotefile)
	{
		Unregister_Object(m_pNotefile);
		delete m_pNotefile;
	}
	m_pNotefile = NULL;
}

void CEditBatchFile::CreateBRBBatch(CString strPath,Page *page)
{
	NotationFile notefile(strPath);
	Page *brbPage = notefile.SetPage("Options");
	brbPage->AppendEntry("Verbose","1");
	brbPage->AppendEntry("BRB","1");
	brbPage = notefile.AddPage(page->GetName());
	Page::NoteIterator *notes = page->MakeNoteIterator();
	Note *note;
	while (note = notes->ReadAndNext())
	{
		const char *entry;
		note->GetEntry(&entry);
		brbPage->AppendEntry(note->GetName(),entry);
	}
	delete notes;
	notefile.Save();
}

bool bDoExport = false;
void CEditBatchFile::OnModify(/*bool bDoExport*/) 
{
	CString strGamePath;
	{
		TSTR ini_file = ip->GetDir(APP_PLUGCFG_DIR);
		ini_file += "\\Plugins.ini";
		Check_Pointer(Stuff::FileStreamManager::Instance);
		Stuff::NotationFile data_file(ini_file);
		const char* read_dir;
		Stuff::Page *tpage = data_file.FindPage("BRBData");
		if (tpage && tpage->GetEntry("GameDir", &read_dir))
		{
			strGamePath = read_dir;
		}
	}
	CString brbPath = strGamePath+"\\content\\games\\brb\\data";
	CString brbFile = brbPath+"\\BrbBatch.batch";

	int count = m_list.GetSelCount();

	if (count>0)
	{
		::gos_DeleteFile(brbFile);
		int *items = new int[count];
		m_list.GetSelItems(count,items);
		for (int x=0;x<count;x++)
		{
			CString str;
			m_list.GetText(items[x],str);
			Page *page = m_pNotefile->FindPage(str);
			if (!bDoExport)
				page->AppendEntry("DoExport","0");
			//Page *page = (Page *)m_list.GetItemData(items[x]);
			CreateBRBBatch(brbFile,page);
		}
		delete items;

		if (ip->ExportToFile(brbFile,true))
		{
			// Export successful, add the pages data to the fullexport.batch
			NotationFile notefile(brbFile);

			NotationFile::PageIterator *pages = notefile.MakePageIterator();
			Page *page;
			Check_Object(pages);
			while (page = pages->ReadAndNext())
			{
				m_pNotefile->DeletePage(page->GetName());
				Page *newpage = m_pNotefile->AddPage(page->GetName());

				Page::NoteIterator *notes = page->MakeNoteIterator();
				Note *note;
				Check_Object(notes);
				while (note = notes->ReadAndNext())
				{
					const char *entry;
					note->GetEntry(&entry);
					if (strnicmp(note->GetName(),"DoExport",8))
						newpage->AppendEntry(note->GetName(),entry);
				}
				delete notes;

			}
			delete pages;
		}
	}
}

void CEditBatchFile::OnCancel() 
{
	// TODO: Add extra cleanup here
	m_pNotefile->IgnoreChanges();
	CDialog::OnCancel();
}

void CEditBatchFile::OnOK() 
{
	m_pNotefile->Save();	
	CDialog::OnOK();
}

void CEditBatchFile::OnAdd() 
{
	CString strGamePath;
	{
		TSTR ini_file = ip->GetDir(APP_PLUGCFG_DIR);
		ini_file += "\\Plugins.ini";
		Check_Pointer(Stuff::FileStreamManager::Instance);
		Stuff::NotationFile data_file(ini_file);
		const char* read_dir;
		Stuff::Page *tpage = data_file.FindPage("BRBData");
		if (tpage && tpage->GetEntry("GameDir", &read_dir))
		{
			strGamePath = read_dir;
		}
	}

	CString strName;
	CString strBrowse;
	CString strType;
	bool bFind = false;
	while (!bFind)
	{
		strBrowse = BrowseDirectory("",this);
		if (strBrowse.GetLength())
		{
			strName = strBrowse;
			{
				if (stricmp(strName.Right(5),"final")==0)
					strName = strName.Left(strName.GetLength()-6);
				else
				{
					// TODO,BUGBUG: this is only until sage re-structures the art repository
					strBrowse += "\\final";
				}
				int index = strName.ReverseFind('\\');
				if (index>3)
				{
					strType = strName.Left(index);
					strName.Delete(0,index+1);
				}

				index = strType.ReverseFind('\\');
				if (index>3)
				{
					strType.Delete(0,index+1);
				}
			}
			Page *page = m_pNotefile->FindPage(strName);
			if (page)
			{
				CString str;
				str.Format("A model named %s already exists in Fullexport.batch, please select a different model",strName);
				MessageBox(str,"Add to Fullexport.batch");
			}
			else
			{
				bFind = true;
			}
		}
		else
		{
			// User pressed cancel
			return;
		}
	}

	int index = m_list.AddString(strName);
	m_list.SetCurSel(index);

	Page *page = m_pNotefile->AddPage(strName);

	// Detect class
	int itype = -1;
	CString strClass;
	if (0==stricmp(strType,"Buildings"))
	{
		itype = 0;
		strClass = "MechWarrior4::Building";
	}
	if (0==stricmp(strType,"Mechs"))
	{
		itype = 1;
		strClass = "MechWarrior4::Mech";
	}
	if (0==stricmp(strType,"Vehicles"))
	{
		itype = 2;
		strClass = "MechWarrior4::Vehicle";
	}
	if (itype >=0)
	{
		page->AppendEntry("Class",strClass);
	}

	CString strPath = strGamePath+"\\content\\"+strType+"\\"+strName+"\\";
	page->AppendEntry("Path",strPath);

	// Detect skeleton
	bool bSkel = false;
	CString strSkel = strBrowse;
	CString str = strSkel+"\\Skeleton\\"+strName+".max";
	if (::gos_DoesFileExist(str))
	{
		strSkel = str;
		bSkel = true;
	}
	else
	{
		str = strSkel+"\\"+strName+".max";
		if (::gos_DoesFileExist(str))
		{
			strSkel = str;
			bSkel = true;
		}
	}
	if (bSkel)
	{
		page->AppendEntry("LODSkel",strSkel);
	}

	//Detect LODs
	char lodDist[3][6][5] =
	{
		{"50","100","250","600","1000","1000"},
		{"30","60","100","200","320","1000"},
		{"25","100","500","1000","1000","1000"}
	};

	BYTE bLod = 0;
	BYTE bDamLod = 0;
	for (int x=0;x<6;x++)
	{
		CString str2 = (0==itype)?"Intact":"Final";
		str.Format("%s\\%s_%s_L%d.max",strBrowse,strName,str2,x);
		if (::gos_DoesFileExist(str))
		{
			bLod |= 1<<x;

			CString str1 = (itype?"LODChar":"LODShape");
			CString strLod;
			strLod.Format("%s%d",str1,x);
			page->AppendEntry(strLod,str);
		}

		str.Format("%s\\%s_Final_Dam_L%d.max",strBrowse,strName,x);
		if (::gos_DoesFileExist(str))
		{
			bDamLod |= 1<<x;

			CString strLod;
			strLod.Format("LODDam%d",x);
			page->AppendEntry(strLod,str);
		}

		if ((bLod & 1<<x) || (bDamLod & 1<<x))
		{
			str = lodDist[itype][x];
			CString strLod;
			strLod.Format("LODDist%d",x);
			page->AppendEntry(strLod,str);
		}
	}

	if (bSkel)
	{
		page->AppendEntry("Obb",strSkel);
	}

	// TODO: Detect Destroyed

	// TODO: Cage

	// TODO: Animations (when sage moves around the art repository structure so I can detect them

	OnModify();
}

void CEditBatchFile::OnRemove() 
{
	int count = m_list.GetSelCount();

	if (count>0)
	{
		int *items = new int[count];
		m_list.GetSelItems(count,items);
		for (int x=0;x<count;x++)
		{
			CString str;
			m_list.GetText(items[x],str);
			m_pNotefile->DeletePage(str);
		}
		delete items;
	}
	OnInitDialog();
}

void CEditBatchFile::OnExport() 
{
	bDoExport = true;
	OnModify();
	bDoExport = false;
}
