// ChildFrm.cpp : implementation of the CChildFrame class
//

#include "stdafx.h"
#include "ContentTrack.h"

#include "ChildFrm.h"
#include "ContentTrackDoc.h"
#include "ContentTrackView.h"
#include "NodeDataValueFileDoc.h"
#include "nodeobjectreferenceview1.h"
#include "findview.h"
#include "UnusedFilesView.h"
#include "MissingFilesView.h"
#include "DirectoryView.h"

#include "WizCopyMission.h"
#include "WizPageProject.h"
#include "WizPageMission.h"
#include "DlgCreateMap.h"
#include <GameOS\ToolOS.hpp>

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

extern CString ReplaceNoCase(CString input,CString strOld,CString strNew,int *pCount = NULL);

/////////////////////////////////////////////////////////////////////////////
// CChildFrame

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
	//{{AFX_MSG_MAP(CChildFrame)
	ON_COMMAND(ID_REFERENCES, OnReferences)
	ON_COMMAND(ID_FILE_NEW, OnFileNew)
	ON_COMMAND(ID_FIND, OnFind)
	ON_COMMAND(ID_MISSINGFILES, OnMissingfiles)
	ON_COMMAND(ID_UNUSEDFILES, OnUnusedfiles)
	ON_COMMAND(ID_WIZ_COPYMISSION, OnWizCopymission)
	ON_COMMAND(ID_DIRECTORY, OnDirectory)
	ON_COMMAND(ID_WIZ_CREATEMAP, OnWizCreatemap)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChildFrame construction/destruction

CChildFrame::CChildFrame()
{
	// TODO: add member initialization code here
	
}

CChildFrame::~CChildFrame()
{
}

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	if( !CMDIChildWnd::PreCreateWindow(cs) )
		return FALSE;

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CChildFrame diagnostics

#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
	CMDIChildWnd::AssertValid();
}

void CChildFrame::Dump(CDumpContext& dc) const
{
	CMDIChildWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChildFrame message handlers

void CChildFrame::OnReferences() 
{
	// Create a new view of this document that contains a tree of the references from the selected node
/*	CNodeDataValueFileDoc *pDoc = (CNodeDataValueFileDoc *)GetActiveDocument();
	CTreeCtrl *pCtrl = &this->GetTreeCtrl();
	pDoc->GetNode()->ViewNode(pCtrl,NULL,2);	


	CView *pView = GetActiveView();
	// If the view is a splitter window then */
	/*m_wndSplitter.SplitColumn(1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CView),CSize(100,100),NULL);
	m_wndSplitter.RecalcLayout();*/
	CCreateContext cc;
    memset(&cc, sizeof(cc), 0);
    cc.m_pNewViewClass = RUNTIME_CLASS(CNodeObjectReferenceView);
    cc.m_pCurrentDoc = GetActiveDocument();
    cc.m_pNewDocTemplate = cc.m_pCurrentDoc ?
        cc.m_pCurrentDoc->GetDocTemplate() : NULL;
    cc.m_pCurrentFrame = this;

	m_wndSplitter.DeleteView(0,1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CNodeObjectReferenceView),CSize(0,0),&cc);
	m_wndSplitter.SetActivePane(0,1);
    // initialize the view

    CView *pView = (CView *)m_wndSplitter.GetPane(0,1);
    if (pView) 
		pView->OnInitialUpdate();
	m_wndSplitter.RecalcLayout();                      // recompute layout 
	//m_wndSplitter.RedrawWindow();

}

BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
	if (m_wndSplitter.CreateStatic(this,1,2))
	{
		m_wndSplitter.CreateView(0,0,pContext->m_pNewViewClass,CSize(300,100),pContext);
		m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CContentTrackView),CSize(10,10),pContext);
		return TRUE;
	}
	return FALSE;
/*	if (m_wndSplitter.Create(this,2,2,CSize(10,10),pContext))
	{
		m_wndSplitter.SetRowInfo(0,200,10);
		m_wndSplitter.SetColumnInfo(0,200,10);
		return true;
	}
	return false;
/*	m_wndSplitter.CreateView(0,0,pContext->m_pNewViewClass,CSize(10,10),pContext);

	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CView),CSize(10,10),pContext);
	m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CView),CSize(10,10),pContext);
	m_wndSplitter.CreateView(1,1,RUNTIME_CLASS(CView),CSize(10,10),pContext);
	//m_wndSplitter.RecalcLayout();*/
//	return CMDIChildWnd::OnCreateClient(lpcs, pContext);
}

void CChildFrame::OnFileNew() 
{
	CDocTemplate *pDocTemplate = (CDocTemplate *) ((CContentTrackApp *)AfxGetApp())->m_mapTemplates[ID_FILE_OPEN];
	pDocTemplate->OpenDocumentFile(NULL);	
}

void CChildFrame::OnFind() 
{
	CCreateContext cc;
    memset(&cc, sizeof(cc), 0);
    cc.m_pNewViewClass = RUNTIME_CLASS(CFindView);
    cc.m_pCurrentDoc = GetActiveDocument();
    cc.m_pNewDocTemplate = cc.m_pCurrentDoc ?
        cc.m_pCurrentDoc->GetDocTemplate() : NULL;
    cc.m_pCurrentFrame = this;

	m_wndSplitter.DeleteView(0,1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CFindView),CSize(0,0),&cc);
	m_wndSplitter.SetActivePane(0,1);
    // initialize the view

    CView *pView = (CView *)m_wndSplitter.GetPane(0,1);
    if (pView) 
		pView->OnInitialUpdate();
	m_wndSplitter.RecalcLayout();                      // recompute layout 	
}

void CChildFrame::OnMissingfiles() 
{
	CCreateContext cc;
    memset(&cc, sizeof(cc), 0);
    cc.m_pNewViewClass = RUNTIME_CLASS(CMissingFilesView);
    cc.m_pCurrentDoc = GetActiveDocument();
    cc.m_pNewDocTemplate = cc.m_pCurrentDoc ?
        cc.m_pCurrentDoc->GetDocTemplate() : NULL;
    cc.m_pCurrentFrame = this;

	m_wndSplitter.DeleteView(0,1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMissingFilesView),CSize(0,0),&cc);
	m_wndSplitter.SetActivePane(0,1);
    // initialize the view

    CView *pView = (CView *)m_wndSplitter.GetPane(0,1);
    if (pView) 
		pView->OnInitialUpdate();
	m_wndSplitter.RecalcLayout();                      // recompute layout 	
}

void CChildFrame::OnUnusedfiles() 
{
	CCreateContext cc;
    memset(&cc, sizeof(cc), 0);
    cc.m_pNewViewClass = RUNTIME_CLASS(CUnusedFilesView);
    cc.m_pCurrentDoc = GetActiveDocument();
    cc.m_pNewDocTemplate = cc.m_pCurrentDoc ?
        cc.m_pCurrentDoc->GetDocTemplate() : NULL;
    cc.m_pCurrentFrame = this;

	m_wndSplitter.DeleteView(0,1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CUnusedFilesView),CSize(0,0),&cc);
	m_wndSplitter.SetActivePane(0,1);
    // initialize the view

    CView *pView = (CView *)m_wndSplitter.GetPane(0,1);
    if (pView) 
		pView->OnInitialUpdate();
	m_wndSplitter.RecalcLayout();                      // recompute layout 	
}

// Add all the other "stuff" to resources.build - buildings, vehicles, etc...
int AddResources(CNodeDisk *pNode,CStringList *pList)
{
	int count = 0;
	static CStringList staticList;
	static int firsttime = 1;
	if (firsttime)
	{
		firsttime = 0;
		// This is the first time, so initialize the staticList
		staticList.RemoveAll();
		staticList.AddHead("players\\");
		staticList.AddHead("maps\\");
		staticList.AddHead("buildings\\");
		staticList.AddHead("weapons\\");
		staticList.AddHead("weaponsubsystems\\");
		staticList.AddHead("mechs\\");
		staticList.AddHead("vehicles\\");
		staticList.AddHead("dropzones\\");
	}
		
	//if (pNode->IsFile())
	{
		//CNodeDataValueFile *pFile = (CNodeDataValueFile *)pNode;
		CNodeDisk *pDisk = pNode;//->GetNodeDisk();
		if (pDisk)
		{
			CString strPath = pDisk->GetPath();
			if (strPath.GetLength())
			{
				if (strPath[0] == '\\')
					strPath.Delete(0,1);
				//strPath.MakeLower();
				CString ext = strPath.Right(5);
				//if (ext == CString(".data"))
				if (0 == strnicmp(ext,".data",5))
				{
					if (strnicmp(strPath,"content\\",8)==0)
						strPath.Delete(0,8);
					CString path = strPath;
					int index = path.Find('\\',0);
					if (index>=0)
					{
						path = path.Left(index+1);
						path.MakeLower();
						if (staticList.Find(path))
						{
							if (NULL == pList->Find(strPath))
							{
								pList->AddHead(strPath);
								count++;
							}
						}
					}
				}
			}
		}
	}

	POSITION pos = pNode->GetFirstChild();
	while (pos)
	{
		CNodeObject *pChild = pNode->GetNextChild(pos);
		if ((pChild->GetClassID() == CLASS_CNODEDISKFILE) || (pChild->GetClassID() == CLASS_CNODEDISKDIRECTORY))
			count += AddResources((CNodeDisk *)pChild,pList);
	}
	return count;
}

int VisitFiles(CNodeObject *pNode)
{
	int count = 0;
	if (NULL == pNode)
		return 0;
	if (pNode->GetClassID() == CLASS_CNODEDISKDIRECTORY)
	{
		POSITION pos = pNode->GetFirstChild();
		while (pos)
		{
			CNodeObject *pChild = pNode->GetNextChild(pos);
			count += VisitFiles(pChild);
		}
	}
	if (pNode->GetClassID() == CLASS_CNODEDISKFILE)
	{
		pNode->SetVisit(VISIT_FLAG1);
		count++;
	}
	return count;
}

void CChildFrame::OnWizCopymission() 
{
	CWizCopyMission dlg("Copy Mission Wizard",AfxGetMainWnd());
	dlg.SetWizardMode();
	CWizPageMission page1;
	dlg.AddPage(&page1);

	CWizPageProject page2;
	dlg.AddPage(&page2);
	if (ID_WIZFINISH == dlg.DoModal())
	{
		CNodeObject *pNode = NULL;
		// Visit flags are used during cloning and should be cleared before we procede
		dlg.m_pSrcDoc->GetRootNode()->ResetVisitAll();	// Cloning flags used to show if we can copy this file
		dlg.m_pDstDoc->GetRootNode()->ResetVisitAll();	// Cloning flags used to show if this file has already been processed
			static int check1 = 1;
		if (check1)
		{
			// Mark the selected directories as Copy-Able
			POSITION pos = dlg.m_listCopyDir.GetHeadPosition();
			while (pos)
			{
				//CObject *pObj = dlg.m_listCopyDir.GetNext(pos);
				CNodeObject *pChild = (CNodeObject *)dlg.m_listCopyDir.GetNext(pos);;
				VisitFiles(pChild);
			}
			CString str = "content\\textures\\maps\\"+dlg.m_strName;
			CNodeDisk *pTDisk = dlg.m_pSrcDoc->FindDirectoryNode(str);
			VisitFiles(pTDisk);
		}

		// Copy the data
		CNodeDataValueFileProject *pSrcProject = dlg.m_pSrcDoc->GetNodeProject();
		CNodeDataValueFileProject *pDstProject = dlg.m_pDstDoc->GetNodeProject();

		pNode = pSrcProject->CreateChild(pSrcProject,KEYTYPE_NOTE,"content\\"+dlg.m_strMission);
		pSrcProject->AddChild(pNode);

		// Copy the TCTD.INI specifically
		CNodeObject *pNodeTct = pSrcProject->CreateChild(pSrcProject,KEYTYPE_NOTE,"content\\maps\\"+dlg.m_strName+"\\tctd.ini");
		pSrcProject->AddChild(pNodeTct);

		SetCurrentDirectory(dlg.m_pDstDoc->GetRootDir());
		// Find the resource.build file in the destination.  It can only be a direct child of the project
		CNodeDisk *pDiskResource = dlg.m_pDstDoc->FindDirectoryNode("content\\resources.build");
		if (NULL == pDiskResource)
		{
			// Create destination resources.build
			// Content directory is assumed when using the rootnode
			pDiskResource = dlg.m_pDstDoc->GetRootNode()->DiskCopyFile("","resources.build");
		}

		// This should copy/merge the files and add to destination project root
		CString strMission = dlg.m_strMission;
		CString newName;
		CString oldName;
		if (dlg.m_bRename)
		{
			newName = dlg.m_strRename;
			oldName = dlg.m_strName;
			int rcount;// = strMission.Replace(oldName,newName);
			CString output = ReplaceNoCase(strMission,oldName,newName,&rcount);
			if (rcount)
			{
				int x=1;
			}
			strMission = output;
		}
		CNodeObject *pCloneTct = dlg.m_pDstDoc->_OnEditPaste(pNodeTct,oldName,newName);
		CNodeObject *pClone = dlg.m_pDstDoc->_OnEditPaste(pNode,oldName,newName);

		// Update resources.build
		// First update the file	
		static int check2 = 1;
		
		CStringList dataList,resList,addList,editorList;
		// dataList are the data members found in copy process
		// reslist are the dataList members found in the source resources.build
		//		- dataList items are removed as they are added to resList
		// addList are the resList items that exist in the destination resources.build
		//		- resList items are removed as they are added to addList
		//		- the remaining reslist is the stuff to add to the destination resources.build
		//			and should have 0 items if there is a rename in the same project
		int rescount = AddResources(dlg.m_pDstDoc->GetRootNode(),&dataList);
		// Copy this list cuz we do the same thing with resources as editor.build (sort of)
		editorList.AddHead(&dataList);

		// TODO: Remove the items in dataList that do not exist in the source resources.build
		{
			NotationFile notefile(*pSrcProject->GetRootPath()+"\\content\\resources.build");
			Page *page = notefile.SetPage("resources\\main");
			if (page)
			{
				Check_Object(page);
				
					Page::NoteIterator *entries = page->MakeNoteIterator();
				Check_Object(entries);

				Note *entry;
				// Enumerate the entries in the section
				while ((entry = entries->ReadAndNext()) != NULL)
				{
					Check_Object(entry);

					CString key(entry->GetName());
					//key.MakeLower();
					const char *value;
					entry->GetEntry(&value);
					CString name1(value);
					CString name2(strMission);
					if (key == "data")
					{	
						POSITION pos = dataList.Find(name1);
						if (pos)
						{
							CString data = dataList.GetAt(pos);
							resList.AddHead(data);
							dataList.RemoveAt(pos);
						}
					}
				}
				delete entries;
			}
			notefile.IgnoreChanges();
		}

		// resources.build is not already loaded so we have to scan it manually
		if (gos_DoesFileExist("content\\resources.build"))
		{
			bool bFoundMap = false;
			bool bFoundMission =false;
			int resaddcount = 0;

			NotationFile notefile("content\\resources.build");
			Page *page = notefile.SetPage("resources\\main");
			if (page)
			{
				Check_Object(page);

				Page::NoteIterator *entries = page->MakeNoteIterator();
				Check_Object(entries);

				Note *entry;
				// Enumerate the entries in the section
				while ((entry = entries->ReadAndNext()) != NULL)
				{
					Check_Object(entry);

					CString key(entry->GetName());
					//key.MakeLower();
					const char *value;
					entry->GetEntry(&value);
					CString name1(value);
					CString name2(strMission);
					//name1.MakeLower();
					//name2.MakeLower();
					if (0 == strnicmp(key,"instance",8))
					//if (key == "instance")
					{
						//if (name1 == name2)
						if (0==strnicmp(name1,name2,name1.GetLength()))
						{
							bFoundMission = true;
						}
					}
					else if (key == "data")
					{	
					// Map should be added automatically
						{
							POSITION pos = resList.Find(name1);
							if (pos)
							{
								resaddcount++;
								CString data = resList.GetAt(pos);
								addList.AddHead(data);
								resList.RemoveAt(pos);
							}
						}
					}
				}
				delete entries;

				if (!bFoundMission)
				{
					page->AppendEntry("instance",strMission);
				}
				// Only add entries to a new resources.build if it exists in the old one
				if (dlg.m_pDstDoc != dlg.m_pSrcDoc)
				{
					POSITION pos = resList.GetHeadPosition();
					while (pos)
					{
						CString str = resList.GetNext(pos);
						page->AppendEntry("data",str);
					}
				}
				else
				{
					Verify(resList.GetCount() == 0);
				}
				if (!bFoundMap || !bFoundMission || (resaddcount>0))
				{
					if (IDYES == MessageBox("Overwrite Resources.build?","Copy Mission",MB_YESNO))
					{
						CString fname("content\\resources.build");
						DWORD attrib = ::GetFileAttributes(fname);
						if (-1 != attrib)
						{
							if (attrib & FILE_ATTRIBUTE_READONLY)
							{
								attrib &= ~FILE_ATTRIBUTE_READONLY;
								::SetFileAttributes(fname,attrib);
							}
						}
						notefile.Save();
					}
					else
						notefile.IgnoreChanges();
				}
			}
			else
			{
				// Error with setpage
				Verify(false);
			}
		}
		else
		{
			// Missing file!!
			Verify(false);
		}

		// Update the contenttracker 
		if (pDiskResource->IsLoaded())
		{
			// If we already loaded this file, we need to update the Node with the new data
			//Verify(false);
		}

		//CStringList edList;
		// TODO: find or create the destination editor.contents
		CNodeDisk *pSrcEditor = dlg.m_pSrcDoc->FindDirectoryNode("content\\editor\\editor.contents");
		if (pSrcEditor)
		{
			// The source has an editor.contents
			//Verify(false);
			// Any model in the source's editor.content that was touched by the copy, copy it to editor.contents
			// Search the copy node for any notation file with a ".data" on the name.  Split the path, 
				// if the fname of the path exists in the editor.contents as a page title, copy that page
			NotationFile notefile(pSrcEditor->GetRootPath()+pSrcEditor->GetPath());
			NotationFile::PageIterator *pages = notefile.MakePageIterator();
			Check_Object(pages);
			Page *page;


			CNodeDisk *pEditor = dlg.m_pDstDoc->GetRootNode()->DiskCopyFile("","editor\\editor.contents");

			NotationFile destfile(dlg.m_pDstDoc->GetRootDir()+pEditor->GetPath());

			while (page = pages->ReadAndNext())
			{
				CString name = page->GetName();
				POSITION pos = editorList.Find(name);
				if (pos)
				{
					editorList.RemoveAt(pos);
					Page *destpage = destfile.SetPage(name);
					destpage->DeleteAllNotes();

					Page::NoteIterator *notes = page->MakeNoteIterator();
					Check_Object(notes);
					Note *note;
					notes->Last();
					while (note = notes->ReadAndPrevious())
					{
						const char *entry;
						note->GetEntry(&entry);
						destpage->AppendEntry(note->GetName(),entry);
					}
					delete notes;

				}
			}
			delete pages;
			notefile.IgnoreChanges();
			destfile.Save();
		}

		CNodeDisk *pDstEditor = dlg.m_pDstDoc->FindDirectoryNode("content\\editor\\editor.contents");
		if (pDstEditor)
		{
			//dlg.m_pDstDoc->_OnEditPaste(pDstEditor,oldName,newName);

		}

		// ** We may want to remove these children from the project... or not
		dlg.m_pSrcDoc->UpdateAllViews(NULL,NULL,NULL);
		dlg.m_pDstDoc->UpdateAllViews(NULL,NULL,NULL);
	}	
}

void CChildFrame::OnDirectory() 
{
	CCreateContext cc;
    memset(&cc, sizeof(cc), 0);
    cc.m_pNewViewClass = RUNTIME_CLASS(CDirectoryView);
    cc.m_pCurrentDoc = GetActiveDocument();
    cc.m_pNewDocTemplate = cc.m_pCurrentDoc ?
        cc.m_pCurrentDoc->GetDocTemplate() : NULL;
    cc.m_pCurrentFrame = this;

	m_wndSplitter.DeleteView(0,1);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CDirectoryView),CSize(0,0),&cc);
	m_wndSplitter.SetActivePane(0,1);
    // initialize the view

    CView *pView = (CView *)m_wndSplitter.GetPane(0,1);
    if (pView) 
		pView->OnInitialUpdate();
	m_wndSplitter.RecalcLayout();                      // recompute layout 	
}

int VisitTreeFiles(CNodeObject *pNode);

void CChildFrame::OnWizCreatemap() 
{
	CDlgCreateMap dlg;
	if (dlg.DoModal() == IDOK)
	{
		CString oldName;
		oldName.Format("%dkcontentmap",dlg.m_iSize);
		CString newName = dlg.m_strName;

		CNodeDataValueFileDoc *pDstDoc = (CNodeDataValueFileDoc *)this->GetActiveDocument();
		CNodeDataValueFileProject *pDstProject = pDstDoc->GetNodeProject();

		CDocTemplate *pDocTemplate = (CDocTemplate *) ((CContentTrackApp *)AfxGetApp())->m_mapTemplates[ID_FILE_OPEN];
		CContentTrackApp *pApp = (CContentTrackApp *)AfxGetApp();
		CString str = pApp->m_strRunDir+"\\template\\template.contenttrack";
		CDocument *pNewDoc = pDocTemplate->OpenDocumentFile(str);
		VERIFY(pNewDoc->IsKindOf(RUNTIME_CLASS(CNodeDataValueFileDoc)));
		CNodeDataValueFileDoc *pSrcDoc = (CNodeDataValueFileDoc *)pNewDoc;

		CNodeDataValueFileProject *pSrcProject = pSrcDoc->GetNodeProject();

		{
			CNodeObject *pSrcNode = pSrcProject->CreateChild(pSrcProject,KEYTYPE_NOTE,"content\\maps\\"+oldName+"\\"+oldName+".instance");
			pSrcProject->AddChild(pSrcNode);

			VisitTreeFiles(pSrcNode);
			CNodeObject *pClone = pDstDoc->_OnEditPaste(pSrcNode,oldName,newName);
		}

		{
			CNodeObject *pSrcNode = pSrcProject->CreateChild(pSrcProject,KEYTYPE_ERF,"content\\skies\\"+oldName+"_sky\\"+oldName+"_sky.erf");
			pSrcProject->AddChild(pSrcNode);

			VisitTreeFiles(pSrcNode);
			CNodeObject *pClone = pDstDoc->_OnEditPaste(pSrcNode,oldName,newName);
		}

		{
			CNodeObject *pSrcNode = pSrcProject->CreateChild(pSrcProject,KEYTYPE_NOTE,"content\\textures\\composttexture\\"+oldName+".index.tcf");
			pSrcProject->AddChild(pSrcNode);

			VisitTreeFiles(pSrcNode);
			CNodeObject *pClone = pDstDoc->_OnEditPaste(pSrcNode,oldName,newName);
		}

		//pSrcProject->AddChild(pSrcNode);
		pSrcDoc->UpdateAllViews(NULL,NULL,NULL);
		pDstDoc->UpdateAllViews(NULL,NULL,NULL);
	}
}
