// DirectoryView.cpp : implementation file
//

#include "stdafx.h"
#include "contenttrack.h"
#include "DirectoryView.h"
#include "NodeDataValueFileDoc.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDirectoryView

IMPLEMENT_DYNCREATE(CDirectoryView, CTreeView)

CDirectoryView::CDirectoryView()
{
}

CDirectoryView::~CDirectoryView()
{
}


BEGIN_MESSAGE_MAP(CDirectoryView, CTreeView)
	//{{AFX_MSG_MAP(CDirectoryView)
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDirectoryView drawing

void CDirectoryView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CDirectoryView diagnostics

#ifdef _DEBUG
void CDirectoryView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CDirectoryView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDirectoryView message handlers

void CDirectoryView::OnInitialUpdate() 
{
	//CTreeCtrl *pCtrl = &GetTreeCtrl();
	CTreeView::OnInitialUpdate();
	

	//CTreeView::OnInitialUpdate();
}

void CDirectoryView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	if (pSender)
	{
		// This was sent from the other view - select the item
		if (GetDocument()->IsKindOf(RUNTIME_CLASS(CNodeDataValueFileDoc)))
		{
			CNodeDataValueFileDoc *pDoc = (CNodeDataValueFileDoc *)GetDocument();
			if (pDoc->m_pActiveChild)
			{
				CNodeObject *pNode = pDoc->m_pActiveChild;
				while (pNode && !pNode->IsFile())
				{
					pNode = pNode->GetParentNode();
				}
				if (pNode)
				{
					CTreeCtrl *pCtrl = &GetTreeCtrl();
					CNodeDisk *pDisk = ((CNodeDataValueFile *)pNode)->GetNodeDisk();
					HTREEITEM hItem;
					if (pDisk->m_mapViewHandles.Lookup((LPVOID)pCtrl,(VOID *&)hItem))
					{
						pCtrl->EnsureVisible(hItem);
						pCtrl->SelectItem(hItem);
					}
				}
			}
		}	
	}
	else
	{
		// Update the tree - see that Files are bolded, file references are added, etc
		if (GetDocument()->IsKindOf(RUNTIME_CLASS(CNodeDataValueFileDoc)))
		{
			CNodeDataValueFileDoc *pDoc = (CNodeDataValueFileDoc *)GetDocument();
			CNodeDisk *pNode = pDoc->GetRootNode();
			InsertNode(pNode,NULL);
		}
	}
}

int CDirectoryView::InsertNode(CNodeObject *pNode,HTREEITEM hParent)
{
	int count = 0;
	if (pNode)
	{
		if ((pNode->GetClassID() == CLASS_CNODEDISKDIRECTORY) || (pNode->GetClassID() == CLASS_CNODEDISKFILE))
		{
			count++;
			char buf[MAX_PATH];
			pNode->GetName(buf,MAX_PATH);

			CTreeCtrl *pCtrl = &GetTreeCtrl();
			CNodeDisk *pDisk = (CNodeDisk *)pNode;
			HTREEITEM hChild;
			if (pDisk->m_mapViewHandles.Lookup(pCtrl,(VOID *&)hChild))
			{
				// Update
				// - Remove the children of hChild
				if (pNode->GetClassID() == CLASS_CNODEDISKFILE)
				{
					CNodeObject *pObj = (CNodeObject *)pCtrl->GetItemData(hChild);
					VERIFY(pObj == pNode);

					HTREEITEM hItem = pCtrl->GetChildItem(hChild);
					while (hItem)
					{
						HTREEITEM hNext = pCtrl->GetNextItem(hItem,TVGN_NEXT);
						pCtrl->DeleteItem(hItem);
						hItem = hNext;
					}
				}
			}
			else
			{
				// Insert
				hChild = pCtrl->InsertItem(buf,hParent);
				pCtrl->SetItemData(hChild,(DWORD)pNode);
				pNode->m_mapViewHandles[pCtrl] = hChild;

				if (pNode->GetClassID() == CLASS_CNODEDISKFILE)
				{
					pCtrl->SetItemState(hChild,TVIS_BOLD,TVIS_BOLD);
				}
			}
			// Add the file's references as children
			if (pNode->GetClassID() == CLASS_CNODEDISKFILE)
			{
				POSITION pos = pNode->GetFirstReference();
				while (pos)
				{
					CNodeObject *pChild = pNode->GetNextReference(pos);
					while (pChild && (!pChild->IsFile() ||(pChild->GetClassID() == CLASS_CNODEDATAVALUEFILEPROJECT)))
						pChild = pChild->GetParentNode();

					// Find the name of the node that loaded this file
					CNodeObject *pChild1 = pChild;
					if (pChild1)
					{
						do
						{
							pChild1 = pChild1->GetParentNode();
						} while (pChild1 && !pChild1->IsFile());
					}

					if (pChild)
					{
						CNodeDisk *pRefDisk;
						if (pChild1)
							pRefDisk = ((CNodeDataValueFile *)pChild1)->GetNodeDisk();
						else
							pRefDisk = ((CNodeDataValueFile *)pChild)->GetNodeDisk();
						HTREEITEM hRefChild = pCtrl->InsertItem(pRefDisk->GetPath(),hChild);
						pCtrl->SetItemData(hRefChild,(DWORD)pChild);
						count++;
					}
				}
			}

			POSITION pos = pNode->GetFirstChild();
			while (pos)
			{
				CNodeObject *pChild = pNode->GetNextChild(pos);
				count += InsertNode(pChild,hChild);
			}
		}
		else
		{
			// This item is one of the file's references
		}
	}
	return count;
}

void CDirectoryView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	if (pNMTreeView->itemNew.state & TVIS_SELECTED)
	{
		CNodeObject *pNode = (CNodeObject *)pNMTreeView->itemNew.lParam;
		if (pNode)
		{
			if ((pNode->GetClassID() == CLASS_CNODEDISKDIRECTORY) || (pNode->GetClassID() == CLASS_CNODEDISKFILE))
			{
			}
			else
			{
				GetDocument()->UpdateAllViews(this,(DWORD)pNode,NULL);
			}
		}
	}
	*pResult = 0;
}

BOOL CDirectoryView::PreCreateWindow(CREATESTRUCT& cs) 
{
	cs.style |= TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_DISABLEDRAGDROP | TVS_FULLROWSELECT | TVS_HASBUTTONS | TVS_LINESATROOT;
	return CTreeView::PreCreateWindow(cs);
}

void CDirectoryView::OnDestroy() 
{
	CTreeView::OnDestroy();
	if (GetDocument()->IsKindOf(RUNTIME_CLASS(CNodeDataValueFileDoc)))
	{
		CNodeDataValueFileDoc *pDoc = (CNodeDataValueFileDoc *)GetDocument();
		CNodeDisk *pNode = pDoc->GetRootNode();
		int count = DestroyNode(pNode);
	}	
}

int CDirectoryView::DestroyNode(CNodeObject *pNode)
{
	int count = 0;
	if (pNode)
	{
		if ((pNode->GetClassID() == CLASS_CNODEDISKDIRECTORY) || (pNode->GetClassID() == CLASS_CNODEDISKFILE))
		{	
			count++;

			CTreeCtrl *pCtrl = &GetTreeCtrl();
			HTREEITEM hChild;
			if (pNode->m_mapViewHandles.Lookup(pCtrl,(VOID *&)hChild))
			{
				pNode->m_mapViewHandles.RemoveKey(pCtrl);
			}
			POSITION pos = pNode->GetFirstChild();
			while (pos)
			{
				CNodeObject *pChild = pNode->GetNextChild(pos);
				count += DestroyNode(pChild);
			}

		}
	}
	return count;
}
