// MapCopyDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MapCopy.h"
#include "MapCopyDlg.h"

//#include <stuff\stuffheaders.hpp>

#ifdef _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()
};

CString g_szbrowsepath;
int CALLBACK BrowseCallbackProc(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,&pidlRoot);

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

	// Localize the descriptive text
	bi.lpszTitle = "Select Destination Folder";

	// 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 = BrowseCallbackProc;
	bi.lParam = (LPARAM)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;
}


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()

/////////////////////////////////////////////////////////////////////////////
// CMapCopyDlg dialog

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

void CMapCopyDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMapCopyDlg)
	DDX_Control(pDX, IDC_LIST_STATUS, m_listStatus);
	DDX_Control(pDX, IDC_LIST_TEMP, m_listDestination);
	DDX_Control(pDX, IDC_LIST_CONTENT, m_listContent);
	DDX_Control(pDX, IDC_EDIT_DIRECTORY, m_editDirectory);
	DDX_Control(pDX, IDC_BROWSE, m_btnBrowse);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMapCopyDlg, CDialog)
	//{{AFX_MSG_MAP(CMapCopyDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
	ON_BN_CLICKED(IDC_RADIO1, OnRadio1)
	ON_BN_CLICKED(IDC_RADIO2, OnRadio2)
	ON_BN_CLICKED(IDC_RADIO3, OnRadio3)
	ON_BN_CLICKED(IDC_ADDTEMP, OnAddtemp)
	ON_BN_CLICKED(IDC_ADDCONTENT, OnAddcontent)
	ON_BN_CLICKED(IDC_UPDATE, OnUpdate)
	ON_BN_CLICKED(IDC_EXECUTE, OnExecute)
	ON_BN_CLICKED(IDC_SYNC_BUILDINGS, OnSyncBuildings)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMapCopyDlg message handlers

BOOL CMapCopyDlg::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
	
	
	char buf[MAX_PATH];
	GetCurrentDirectory(MAX_PATH,buf);

	m_strGameDir = buf;

	buf[1] = '\0';
	CString tempdir = CString(buf)+":\\temp";
	m_editDirectory.SetWindowText(tempdir);

	SendDlgItemMessage(IDC_RADIO1,BM_CLICK,0,0);

	ScanContentMaps();
//	ScanDestMaps();


  m_listStatus.SetHorizontalExtent(700);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMapCopyDlg::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 CMapCopyDlg::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 CMapCopyDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMapCopyDlg::OnBrowse() 
{
	CString dest;
	m_editDirectory.GetWindowText(dest);
	g_szbrowsepath = dest;
	dest = BrowseDirectory(dest,&m_editDirectory);
	m_editDirectory.SetWindowText(dest);
	ScanDestMaps();
}

void CMapCopyDlg::OnRadio1() 
{
	m_copymode = 0;
	ScanDestMaps();
}

void CMapCopyDlg::OnRadio2() 
{
	m_copymode = 1;
	ScanDestMaps();
}

void CMapCopyDlg::OnRadio3() 
{
	m_copymode = 2;
}

void CMapCopyDlg::OnAddtemp() 
{
	int maxcount = m_listContent.GetSelCount();
	int *items = new int[maxcount];
	m_listContent.GetSelItems(maxcount,items);
	for (int x=0;x<maxcount;x++)
	{
		CString name;
		m_listContent.GetText(items[x],name);

		if (LB_ERR == m_listDestination.FindString(-1,name))
		{
			int index = m_listDestination.AddString(name);
			m_listDestination.SetItemData(index,1);
		}
	}
	delete items;
}

void CMapCopyDlg::OnAddcontent() 
{
	int maxcount = m_listDestination.GetSelCount();
	int *items = new int[maxcount];	
	m_listDestination.GetSelItems(maxcount,items);
	for (int x=0;x<maxcount;x++)
	{
		CString name;
		m_listDestination.GetText(items[x],name);

		if (LB_ERR == m_listContent.FindString(-1,name))
		{
			int index = m_listContent.AddString(name);
			m_listContent.SetItemData(index,1);
		}
	}
	delete items;
}

void CMapCopyDlg::OnUpdate() 
{
	ScanDestMaps();
	
}

void CMapCopyDlg::OnExecute() 
{
	CString src;
	CString dst;
		//CStringList listMaps;
	
	CString dest;
	m_editDirectory.GetWindowText(dest);


	switch (m_copymode)
	{
	case 0:
		// Content->Content
	case 1:
		{
			// Content->Temp	
			// Copy the items from content to dest

			for (int x=0;x<m_listDestination.GetCount();x++)
			{
				if (m_listDestination.GetItemData(x))
				{
					CString name;
					m_listDestination.GetText(x,name);
					CopyContent(m_strGameDir,dest,name);

					if (0 == m_copymode)
					{
						// Update resources.build
						{
							NotationFile notefile(dest+"\\content\\resources.build");
							Page *page = notefile.GetPage("resources\\main");
							Check_Object(page);
							page->AppendEntry("data","maps\\"+name+"\\"+name+".data");
							page->AppendEntry("instance","missions\\"+name+"\\"+name+".instance");

							notefile.Save();
						}
							// Update editor.contents
						{

						}
					}
				}
			}
				break;

			{
			}
			break;
		}
	case 2:
		{
			// Temp->Content
				// Copy the items from dest to content
			for (int x=0;x<m_listContent.GetCount();x++)
			{
				if (m_listContent.GetItemData(x))
				{
					CString name;
					m_listContent.GetText(x,name);
					CopyContent(dest,m_strGameDir,name);

					{
						NotationFile notefile(m_strGameDir+"\\content\\resources.build");
						Page *page = notefile.GetPage("resources\\main");
						Check_Object(page);
						page->AppendEntry("data","maps\\"+name+"\\"+name+".data");
						page->AppendEntry("instance","missions\\"+name+"\\"+name+".instance");
					}
					// Update editor.contents
					{

					}
				}
			}
			break;
		}
	}

	ScanContentMaps();
	ScanDestMaps();
}

int CMapCopyDlg::ScanContentMaps()
{
	// Clear all items in list
	int count = m_listContent.GetCount();
	for (int x=0;x<count;x++)
	{
		m_listContent.DeleteString(0);
	}

	// Get this from resources.build
	NotationFile notefile(m_strGameDir+"\\content\\resources.build");
	Page *page = notefile.GetPage("resources\\main");
	if (page)
	{
		Check_Object(page);
		Page::NoteIterator *iterator = page->MakeNoteIterator();
		Check_Object(iterator);
		iterator->First();
		Note *entry;
		while (entry = iterator->ReadAndNext())
		{
			Check_Object(entry);
			const char *name = entry->GetName();
			const char *value;
			entry->GetEntry(&value);
			if (strnicmp(name,"data",4)==0)
			{
				if (strnicmp(value,"maps",4)==0)
				{
					Stuff::MString mapname = value;
					Stuff::StripExtension(&mapname);
					Stuff::StripDirectory(&mapname);
					int index = m_listContent.AddString(mapname);
					m_listContent.SetItemData(index,0);
				}
			}
		}
		delete iterator;
	}
	return 0;
}

int CMapCopyDlg::ScanDestMaps()
{
	// Clear all items in list
	int count = m_listDestination.GetCount();
	for (int x=0;x<count;x++)
	{
		m_listDestination.DeleteString(0);
	}

	// Get the list from the destination directory
	CString strDest;
	m_editDirectory.GetWindowText(strDest);



	if (0 == m_copymode)
	{
		// Get this from resources.build
		NotationFile notefile(strDest+"\\content\\resources.build");
		if (notefile.FindPage("resources\\main"))
		{
			Page *page = notefile.GetPage("resources\\main");
			if (page)
			{
				Check_Object(page);
				Page::NoteIterator *iterator = page->MakeNoteIterator();
				Check_Object(iterator);
				iterator->First();
				Note *entry;
				while (entry = iterator->ReadAndNext())
				{
					Check_Object(entry);
					const char *name = entry->GetName();
					const char *value;
					entry->GetEntry(&value);
					if (strnicmp(name,"data",4)==0)
					{
						if (strnicmp(value,"maps",4)==0)
						{
							Stuff::MString mapname = value;
							Stuff::StripExtension(&mapname);
							Stuff::StripDirectory(&mapname);
							int index = m_listDestination.AddString(mapname);
							m_listDestination.SetItemData(index,0);
						}
					}
				}
				delete iterator;
			}
		}
	}
	else
	{
		CFileFind filefind;
		if (filefind.FindFile(strDest+"\\content\\maps\\*.*"))
		{
			bool lastfile = false;
			while (1)
			{
				lastfile = !filefind.FindNextFile();
				if (!filefind.IsDots())
				{
					if (filefind.IsDirectory())
					{
						int index = m_listDestination.AddString(filefind.GetFileTitle());
						// Set to zero if origial - will be set to 1 if it is new (do be added)
						m_listDestination.SetItemData(index,0);
					}
				}
				if (lastfile)
					break;
			}
			filefind.Close();
		}
	}
	return 0;
}

int CMapCopyDlg::CopyDirectory(CString src, CString dst,CString param)
{
	CString action;
	action = "md "+dst;
	m_listStatus.AddString(action);
	//ShellExecute(NULL,NULL,"md",dst,NULL,SW_HIDE);
	//CreateDirectory(dst,NULL);
	//system(action);
	for (int x=0;x<dst.GetLength();x++)
	{
		if (dst[x] == '\\')
		{
			CString str = dst.Left(x+1);
			if (str.GetLength()>3)
				CreateDirectory(str,NULL);
		}
	}
	CreateDirectory(dst,NULL);

	action = "\"" + src + "\" \"" +dst+"\" "+param;
	m_listStatus.AddString("xcopy "+action);
	//system(action);
	HINSTANCE  nRet = ShellExecute(NULL,NULL,"xcopy",action,NULL,SW_HIDE);

  if (nRet <= (HINSTANCE)32)
  {
    CString errStr;
    switch ((int)nRet)
    {
    case 0:  
      errStr = "Operating system out of resources.";
      break;

    case ERROR_FILE_NOT_FOUND  :
      errStr = "ERROR_FILE_NOT_FOUND";
      break;

    case ERROR_PATH_NOT_FOUND  :
      errStr = "ERROR_PATH_NOT_FOUND ";
      break;

    case ERROR_BAD_FORMAT      :
      errStr = "ERROR_BAD_FORMAT      ";
      break;

    case SE_ERR_ACCESSDENIED   :
      errStr = "SE_ERR_ACCESSDENIED  ";
      break;

    case SE_ERR_ASSOCINCOMPLETE:
      errStr = "SE_ERR_ASSOCINCOMPLETE";
      break;

    case SE_ERR_DDEBUSY        :
      errStr = "SE_ERR_DDEBUSY ";
      break;

    case SE_ERR_DDEFAIL        :
      errStr = "SE_ERR_DDEFAIL";
      break;

    case SE_ERR_DDETIMEOUT     :
      errStr = "SE_ERR_DDETIMEOUT   ";
      break;

    case SE_ERR_DLLNOTFOUND    :
      errStr = "SE_ERR_DLLNOTFOUND";
      break;

    case SE_ERR_NOASSOC        :
      errStr = "SE_ERR_NOASSOC";
      break;

    case SE_ERR_OOM            :
      errStr = "SE_ERR_OOM";
      break;

    case SE_ERR_SHARE          :
      errStr = "SE_ERR_SHARE";
      break;
    }
    errStr += " received while performing \r\n";
    errStr += "'xcopy ";
    errStr += action;
    errStr += "'";
    MessageBox((LPCSTR)errStr, "Copy error", MB_OK);
  }

	return 0;
}

// Copy only files in src that don't exist in dst
int CMapCopyDlg::SyncDirectory(CString src, CString dst)
{
	// Find everything in src that is not in dst and copy those
	CStringList listdst;

	CFileFind filefind;
	if (filefind.FindFile(dst+"\\*.*"))
	{
		bool lastfile = false;
		while (1)
		{
			lastfile = !filefind.FindNextFile();
			if (!filefind.IsDots())
			{
				//if (!filefind.IsDirectory())
				{
					listdst.AddHead(filefind.GetFileName());
				}
			}
			if (lastfile)
				break;
		}
		filefind.Close();
	}

	if (filefind.FindFile(src+"\\*.*"))
	{
		bool lastfile = false;
		while (1)
		{
			lastfile = !filefind.FindNextFile();
			if (!filefind.IsDots())
			{
				//if (!filefind.IsDirectory())
				{
					CString name = filefind.GetFileName();
					if (NULL ==listdst.Find(name))
					{
						CopyDirectory(src+"\\"+name,dst+"\\"+name,"/E");
					}
				}
			}
			if (lastfile)
				break;
		}
		filefind.Close();
	}
	return 0;
}

int CMapCopyDlg::CopyContent(CString src,CString dst,CString name)
{
	CopyDirectory(src+"\\content\\maps\\"+name,
		dst+"\\content\\maps\\"+name,
		"/E");
	CopyDirectory(src+"\\content\\textures\\maps\\"+name,
		dst+"\\content\\textures\\maps\\"+name,
		"/E");
	CopyDirectory(src+"\\content\\textures\\composttexture\\"+name+"*.*",
		dst+"\\content\\textures\\composttexture",
		"/E");
	CopyDirectory(src+"\\content\\missions\\"+name,
		dst+"\\content\\missions\\"+name,
		"/E");
	CopyDirectory(src+"\\content\\textures\\"+name+"*.*",
		dst+"\\content\\textures");

	SyncDirectory(src+"\\content\\buildings",dst+"\\content\\buildings");
	// Copy content\maps\<mapname>
	// Copy content\textures\maps\<mapname>
	// Copy content\textures\composttexture\<mapname>*
	// Copy content\textures\composite\index...
	// Copy content\building (only the new ones)
	// Copy content\misions\<mapname>
	return 0;
}

void CMapCopyDlg::OnSyncBuildings() 
{
	CString dest;
	m_editDirectory.GetWindowText(dest);
	SyncDirectory(m_strGameDir+"\\content\\buildings",dest+"\\content\\buildings");
}
