// DlgProject.cpp : implementation file
//

#include "stdafx.h"
#include "Multitron.h"
#include "DlgProject.h"

#include <imagelib\image.h>

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

/////////////////////////////////////////////////////////////////////////////
// CDlgProject dialog


CDlgProject::CDlgProject(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgProject::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDlgProject)
	//}}AFX_DATA_INIT

	m_pNoteFile = NULL;
	m_pDocument = (CMultitronDoc *)-1;
}


void CDlgProject::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgProject)
	DDX_Control(pDX, IDC_TREE_DATA, m_wndTreeData);
	DDX_Control(pDX, IDC_PREVIEW, m_wndPreview);
	DDX_Control(pDX, IDC_LIST_HINTPAGE, m_wndListHintPage);
	DDX_Control(pDX, IDC_COMBO_HINTFILENAME, m_wndComboHintFileName);
	DDX_Control(pDX, IDC_TREE_FILES, m_wndTreeFiles);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDlgProject, CDialog)
	//{{AFX_MSG_MAP(CDlgProject)
	ON_CBN_SELENDOK(IDC_COMBO_HINTFILENAME, OnSelendokComboHintfilename)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_FILES, OnSelchangedTreeFiles)
	ON_LBN_SELCHANGE(IDC_LIST_HINTPAGE, OnSelchangeListHintpage)
	ON_WM_DRAWITEM()
	ON_LBN_DBLCLK(IDC_LIST_HINTPAGE, OnDblclkListHintpage)
	ON_WM_CONTEXTMENU()
	ON_COMMAND(ID_ADD_MEGATEXTURE, OnAddMegatexture)
	ON_COMMAND(ID_ADD_TEXTUREHINT, OnAddTexturehint)
	ON_COMMAND(ID_REMOVE_TEXTUREHINT, OnRemoveTexturehint)
	ON_NOTIFY(NM_DBLCLK, IDC_TREE_DATA, OnDblclkTreeData)
	ON_COMMAND(ID_OPEN_TEXTURE, OnOpenTexture)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgProject message handlers

int CDlgProject::AddItem(CFileNode *pNode,HTREEITEM hParent)
{
	int count = 0;
	if (pNode)
	{
		count++;
		CString name = pNode->strName;
		if (TVI_ROOT != hParent)
		{
			char fname[MAX_PATH];
			_splitpath(name,NULL,NULL,fname,NULL);
			name = fname;
		}
		HTREEITEM hItem = m_wndTreeFiles.InsertItem(name,hParent);
		if (TVI_ROOT != hParent)
			m_wndTreeFiles.SetItemData(hItem,(DWORD)pNode);
		POSITION pos = pNode->listChildren.GetHeadPosition();
		while (pos)
		{
			CFileNode *pChild = (CFileNode *)pNode->listChildren.GetNext(pos);
			count += AddItem(pChild,hItem);
		}
	}
	return count;
}

void CDlgProject::OnSelchangedTreeFiles(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	CFileNode *pNode = (CFileNode *)pNMTreeView->itemNew.lParam;
	m_wndComboHintFileName.ResetContent();

	if (pNode)
	{
		int count = 0;
		Stuff::NotationFile::PageIterator *pages = pNode->pFile->MakePageIterator();
		Stuff::Page *page;
		while (NULL != (page = pages->ReadAndNext()))
		{
			CString pagename = page->GetName();
			
		
			Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
			Stuff::Note *note;
			while (NULL != (note = notes->ReadAndNext()))
			{
				const char *entry;
				note->GetEntry(&entry);

				int index = m_wndComboHintFileName.AddString(entry);
				m_wndComboHintFileName.SetItemData(index,(DWORD)note);

				// Set texturepool by default
				if (0==stricmp(note->GetName(),"texturepool"))
				{
					count++;
					m_wndComboHintFileName.SetCurSel(index);
				}
			}
			delete notes;
			/*
			const char *entry;
			if (page->GetEntry("texturepool",&entry))
			{
				count++;
				int index = m_wndComboHintFileName.AddString(entry);
				CString filename("content\\");
				filename+=entry;

				CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
				Stuff::NotationFile *pHintFile = pApp->GetHintFile(filename);
				m_wndComboHintFileName.SetItemData(index,(DWORD)pHintFile);
			}*/
		}
		delete pages;
		if ((0==count)&&m_wndComboHintFileName.GetCount())
			m_wndComboHintFileName.SetCurSel(0);
	}
	OnSelendokComboHintfilename();
	*pResult = 0;
}

void CDlgProject::OnSelendokComboHintfilename() 
{
	m_wndListHintPage.ResetContent();
	m_BackBuffer.DeleteObject();
	m_wndPreview.Invalidate();
	m_pNoteFile=NULL;
	int sel = m_wndComboHintFileName.GetCurSel();
	if (CB_ERR != sel)
	{
		Stuff::Note *pNote = (Stuff::Note *)m_wndComboHintFileName.GetItemData(sel);
		if (pNote)
		{
			Check_Object(pNote);
			const char *entry;
			pNote->GetEntry(&entry);
			CString filename("content\\");
			filename+=entry;

			CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
			CMultitronDoc *pMDoc = (CMultitronDoc *)m_pDocument;
			Stuff::NotationFile *pFile = pMDoc->GetHintFile(filename);
			m_pNoteFile = pFile;

			CString notename = pNote->GetName();
			if (0==stricmp(notename,"texturepool"))
				SetDataTexturepool(pFile);
			else if (0==stricmp(notename,"data"))
				SetDataBrowseNotation(pFile);
			else if (0==stricmp(notename,"instance"))
				SetDataBrowseNotation(pFile);
			else if (0==stricmp(notename,"notation"))
				SetDataBrowseNotation(pFile);
			else
			{
				m_wndTreeData.ShowWindow(SW_HIDE);
				m_wndListHintPage.ShowWindow(SW_HIDE);
			}
			
			DWORD attrib = GetFileAttributes(filename);
			if (-1 != attrib)
			{
				if (attrib & FILE_ATTRIBUTE_READONLY)
				{
					CString str;
					str.Format("%s is Read-Only.  Would you like to enable write permission?",filename);
					if (IDYES == MessageBox(str,"Read Hint File",MB_YESNO))
					{
						attrib &= ~FILE_ATTRIBUTE_READONLY;
						SetFileAttributes(filename,attrib);
					}
				}
			}
		}
	}
	else
	{
		m_wndTreeData.ShowWindow(SW_HIDE);
		m_wndListHintPage.ShowWindow(SW_HIDE);
	}
}

void CDlgProject::OnSelchangeListHintpage() 
{
	int nCount = m_wndListHintPage.GetSelCount();
	int *items = new int[nCount];
	int err = m_wndListHintPage.GetSelItems(nCount,items);	
	CPtrList list;
	for (int x=0;x<nCount;x++)
	{
		DWORD data = m_wndListHintPage.GetItemData(items[x]);
		list.AddTail((LPVOID)data);
	}
	delete items;

	m_BackBuffer.DeleteObject();
	m_wndPreview.Invalidate();
	Image image;

	if (list.GetCount())
	{
		Stuff::Page *page = (Stuff::Page *)list.GetHead();
		if (page)
		{
			CString imagename = page->GetName();
			const char *entry;
			if (page->GetEntry("Alias",&entry))
			{
				imagename = entry;
			}
			CString path = "content\\textures\\"+imagename;

			image.Delete();

			CString fullname = path+".png";
			if (gos_DoesFileExist(fullname))
			{
				image.Load((char *)(LPCTSTR)fullname);
			}
			else
			{
				fullname = path+".tga";
				if (gos_DoesFileExist(fullname))
				{
					image.Load((char *)(LPCTSTR)fullname);
				}
				else
				{
					return;
				}
			}
			
			if(image.GetBpp()==32)
				image.MaskTo(RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000));
			else
				image.MaskTo(RGBMask(0x00ff0000,0x0000ff00,0x000000ff));
		
			CDC  memDC,*hfDC;
			hfDC=GetDC();

			BOOL bres;
			bres=m_BackBuffer.CreateCompatibleBitmap(hfDC,image.GetWidth(),image.GetHeight());
			Verify(bres);

			memDC.CreateCompatibleDC(hfDC);
			memDC.SelectObject(&m_BackBuffer);

			BITMAPINFOHEADER bhd;
			BITMAPINFO       binf;
			bhd.biSize=sizeof(BITMAPINFOHEADER);
			bhd.biWidth=image.GetWidth(); bhd.biHeight=-image.GetHeight();
			bhd.biPlanes=1;
			bhd.biBitCount=image.GetBpp();
			bhd.biCompression=BI_RGB;
			bhd.biSizeImage=0;
			bhd.biClrImportant=0;
			binf.bmiHeader=bhd;

			BYTE *imgdat=(BYTE *)(image.Lock());

			DWORD isize = image.GetWidth()*image.GetHeight()*(image.GetBpp()>>3);
			if (32==image.GetBpp())
			{
				m_BackBuffer.SetBitmapBits(isize,imgdat);
			}
			else
			{
				SetDIBitsToDevice(memDC,0,0,image.GetWidth(),
				image.GetHeight(),0,0,0,image.GetWidth(),imgdat,
				&binf,DIB_RGB_COLORS);  
			}
			image.UnLock();

			memDC.DeleteDC();
			ReleaseDC(hfDC);
		}
	}
}

void CDlgProject::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	switch (lpDrawItemStruct->CtlID)
	{
	case IDC_PREVIEW:
		{
			HBITMAP hBitmap = m_BackBuffer;
			if (hBitmap)
			{
				CDC  memDC;
				int res;
				
				BITMAP bmp;
				res=m_BackBuffer.GetBitmap(&bmp);
				Verify(res);
				
				BOOL bres;
				CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
				bres=memDC.CreateCompatibleDC(pDC);
				Verify(bres);
				memDC.SelectObject(&m_BackBuffer);
				CRect hfrct;
				m_wndPreview.GetClientRect(&hfrct);

				pDC->SetStretchBltMode(COLORONCOLOR);
				bres=pDC->StretchBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),NULL,0,0,BLACKNESS);
				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,SRCCOPY);
				Verify(bres);
				memDC.DeleteDC();
			}
			return;
		}
	}
	CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

void CDlgProject::OnDblclkListHintpage() 
{
	OnOpenTexture();
}

void CDlgProject::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	CMenu *pMenu = AfxGetMainWnd()->GetMenu();
	int i = 0;
	switch (pMenu->GetMenuItemCount())
	{
	case 4:i=2;break;
	case 6:i=3;break;
	case 10:i=4;break;
	}
	if (i)
	{
		CMenu *pSubMenu = pMenu->GetSubMenu(i);
		pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x, point.y, this, NULL);
	}
}

void CDlgProject::OnAddMegatexture() 
{
	int nCount = m_wndListHintPage.GetSelCount();
	int *items = new int[nCount];
	int err = m_wndListHintPage.GetSelItems(nCount,items);	
	CPtrList list;
	for (int x=0;x<nCount;x++)
	{
		DWORD data = m_wndListHintPage.GetItemData(items[x]);
		list.AddTail((LPVOID)data);
	}
	delete items;

	if (0==nCount)
		return;

	Stuff::Page *page = (Stuff::Page *)list.GetHead();
	Check_Object(page);

	// Create a megatexture with the name of the first item with underscore first character
	CString meganame = CString("_")+page->GetName();
	int index = m_wndComboHintFileName.GetCurSel();
	if (CB_ERR != index)
	{
		Stuff::NotationFile *pFile = m_pNoteFile;

		if (pFile)
		{
			// Put all of the textures at 0 0 and let the TextureView arrange them
			Stuff::Page *megapage = pFile->AddPage(meganame);
			megapage->AppendEntry("PageSize","512 512");
			POSITION pos = list.GetHeadPosition();
			while (pos)
			{
				Stuff::Page *page = (Stuff::Page *)list.GetNext(pos);
				Check_Object(page);

				CString name = page->GetName();
				const char *entry;
				if (page->GetEntry("Alias",&entry))
				{
					name = entry;
				}
				megapage->AppendEntry(name,"");
			}

			CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
			CDocTemplate *pTemplate = (CDocTemplate *)pApp->m_mapTemplate[ID_FILE_NEW];

			pTemplate->OpenDocumentFile((LPCTSTR)megapage);

			OnSelendokComboHintfilename();
			int count = m_wndListHintPage.GetCount();
			for (int x=0;x<count;x++)
			{
				LPVOID lp = (LPVOID)m_wndListHintPage.GetItemData(x);

				if (lp == (LPVOID)megapage)
				{
					m_wndListHintPage.SetSel(x);
					OnSelchangeListHintpage();
					break;
				}
			}
		}
	}
}

void CDlgProject::OnAddTexturehint() 
{
	int index = m_wndComboHintFileName.GetCurSel();
	if (CB_ERR != index)
	{
		Stuff::NotationFile *pFile = m_pNoteFile;

		if (pFile)
		{
			CFileDialog dlg(true,".png","content\\textures\\*.*",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT,"Image Files (*.png;*.tga)|*.png;*.tga||",AfxGetMainWnd());
			if (IDOK == dlg.DoModal())
			{
				CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
				CDocTemplate *pTemplate = (CDocTemplate *)pApp->m_mapTemplate[ID_FILE_NEW];
				SetCurrentDirectory(pApp->m_strRunDir);

				CPtrList list;
				POSITION pos = dlg.GetStartPosition();
				while (pos)
				{
					CString pathname = dlg.GetNextPathName(pos);
					char name[MAX_PATH];
					_splitpath(pathname,NULL,NULL,name,NULL);

					Stuff::Page *page = pFile->AddPage(name);
					list.AddTail((LPVOID)page);
					pTemplate->OpenDocumentFile((LPCTSTR)page);
				}
				OnSelendokComboHintfilename();

				int count = m_wndListHintPage.GetCount();
				for (int x=0;x<count;x++)
				{
					LPVOID lp = (LPVOID)m_wndListHintPage.GetItemData(x);

					pos = list.Find(lp);
					if (pos)
					{
						list.RemoveAt(pos);
						m_wndListHintPage.SetSel(x);
					}
					if (list.GetCount()==0)
						break;
				}
				OnSelchangeListHintpage();
			}
		}
	}
}

void CDlgProject::OnRemoveTexturehint() 
{
	int index = m_wndComboHintFileName.GetCurSel();
	if (CB_ERR != index)
	{
		Stuff::NotationFile *pFile = m_pNoteFile;

		if (pFile)
		{
			CMultitronDoc *pDoc = (CMultitronDoc *)m_pDocument;

			int nCount = m_wndListHintPage.GetSelCount();
			int *items = new int[nCount];
			int err = m_wndListHintPage.GetSelItems(nCount,items);	
			for (int x=0;x<nCount;x++)
			{
				Stuff::Page *page = (Stuff::Page *)m_wndListHintPage.GetItemData(items[x]);
				Check_Object(page);
				pDoc->RemoveTexture(page);
			}
			delete items;

			pDoc->UpdateAllViews(NULL);
		}
	}
}

int CDlgProject::SetDataTexturepool(Stuff::NotationFile *pFile)
{	
	m_wndListHintPage.ResetContent();
	m_wndListHintPage.ShowWindow(SW_SHOW);
	m_wndTreeData.ShowWindow(SW_HIDE);
	Stuff::NotationFile::PageIterator *pages = pFile->MakePageIterator();
	Stuff::Page *page;
	while (NULL != (page = pages->ReadAndNext()))
	{
		CString pagename = page->GetName();
		
		int index = m_wndListHintPage.AddString(pagename);
		m_wndListHintPage.SetItemData(index,(DWORD)page);
	}
	delete pages;
	return 0;
}

int CDlgProject::SetDataBrowseNotation(Stuff::NotationFile *pFile)
{
	m_wndTreeData.DeleteAllItems();
	m_wndTreeData.ShowWindow(SW_SHOW);
	m_wndListHintPage.ShowWindow(SW_HIDE);
	Stuff::NotationFile::PageIterator *pages = pFile->MakePageIterator();
	Stuff::Page *page;
	while (NULL != (page = pages->ReadAndNext()))
	{
		CString pagename = page->GetName();
		
		HTREEITEM hPage = m_wndTreeData.InsertItem(pagename,TVI_ROOT);
		m_wndTreeData.SetItemData(hPage,(DWORD)page);

		Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
		Stuff::Note *note;
		while (NULL != (note = notes->ReadAndNext()))
		{
			CString notename = note->GetName();
			const char *entry;
			note->GetEntry(&entry);
			CString str;
			str.Format("%s=%s",notename,entry);
			HTREEITEM hNote = m_wndTreeData.InsertItem(str,hPage);
			m_wndTreeData.SetItemData(hNote,(DWORD)note);
		}
		delete notes;
	
		m_wndTreeData.Expand(hPage,TVE_EXPAND);
	}
	delete pages;
	return 0;
}

void CDlgProject::OnDblclkTreeData(NMHDR* pNMHDR, LRESULT* pResult) 
{	
	OnOpenTexture();
	*pResult = 0;
}

CDocument *CDlgProject::SetDocument(CMultitronDoc *pDoc)
{
	BOOL bReset = true;
	if (pDoc == m_pDocument)
		bReset = false;
	CMultitronDoc *pBack = m_pDocument;
	if (-1 != (DWORD)pDoc)
		m_pDocument = pDoc;
	else
	{
		bReset = false;
	}

	if (m_wndTreeFiles.GetSafeHwnd())
	{
		if (bReset)
			m_wndTreeFiles.DeleteAllItems();
		if (pDoc)
		{
			if (bReset)
			{
				CFileNode *pNode = m_pDocument->GetFileNode();
				AddItem(pNode);	
			}
			OnSelendokComboHintfilename();
		}
	}
	return pBack;
}

void CDlgProject::OnOpenTexture() 
{
	if (m_wndListHintPage.GetSafeHwnd())
	{
		CDocument *pDoc = NULL;


		int nCount = m_wndListHintPage.GetSelCount();
		if (nCount)
		{
			int *items = new int[nCount];
			int err = m_wndListHintPage.GetSelItems(nCount,items);	
			for (int x=0;x<nCount;x++)
			{
				DWORD data = m_wndListHintPage.GetItemData(items[x]);
				if (0==x)
					pDoc = m_pDocument->OpenTexture((Stuff::Page *)data);
				else
					pDoc->SetPathName((LPCTSTR)data);
			}
			delete items;
		}
		if (pDoc)
			pDoc->UpdateAllViews(NULL);
	}

	if (m_wndTreeData.GetSafeHwnd())
	{
		HTREEITEM hItem = m_wndTreeData.GetSelectedItem();

		if (hItem)
		{
			CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
			CDocTemplate *pTemplate = (CDocTemplate *)pApp->m_mapTemplate[ID_FILE_NEW_NOTEFILE];

			DWORD data = m_wndTreeData.GetItemData(hItem);
			if (data)
				pTemplate->OpenDocumentFile((LPCTSTR)data);
		}
	}
	m_pDocument->UpdateAllViews(NULL);
}
