// TextureView.cpp : implementation file
//

#include "stdafx.h"
#include "Multitron.h"
#include "TextureView.h"
#include "TextureDoc.h"
#include "MainFrm.h"

#include <GameOs\TooLOS.hpp>
#include <imagelib\image.h>

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

/////////////////////////////////////////////////////////////////////////////
// CTextureView

IMPLEMENT_DYNCREATE(CTextureView, CView)

CTextureView::CTextureView()
{
}

CTextureView::~CTextureView()
{
}


BEGIN_MESSAGE_MAP(CTextureView, CView)
	//{{AFX_MSG_MAP(CTextureView)
	ON_WM_CREATE()
	ON_BN_CLICKED(IDC_ADD, OnAdd)
	ON_BN_CLICKED(IDC_DELETE, OnDelete)
	ON_LBN_SELCHANGE(IDC_LIST_PAGE, OnSelchangeListPage)
	ON_CBN_SELENDOK(IDC_COMBO_VALUE, OnSelendokComboValue)
	ON_BN_CLICKED(IDC_APPLY, OnApply)
	ON_BN_CLICKED(IDC_APPLY_ALIAS, OnApplyAlias)
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(ID_ADD_MIPMAP,ID_ADD_RESOURCIFY,OnAddMenuItems)
	ON_UPDATE_COMMAND_UI(IDC_APPLY, OnUpdateUI)
	ON_UPDATE_COMMAND_UI(IDC_APPLY_ALIAS, OnUpdateUI)
	ON_UPDATE_COMMAND_UI(IDC_EDIT_PAGENAME, OnUpdateUI)
	ON_UPDATE_COMMAND_UI(IDC_EDIT_ALIASNAME, OnUpdateUI)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTextureView drawing

void CTextureView::OnDraw(CDC* pDC)
{
}

/////////////////////////////////////////////////////////////////////////////
// CTextureView diagnostics

#ifdef _DEBUG
void CTextureView::AssertValid() const
{
	CView::AssertValid();
}

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

/////////////////////////////////////////////////////////////////////////////
// CTextureView message handlers

BOOL CTextureView::PreCreateWindow(CREATESTRUCT& cs) 
{
	return CView::PreCreateWindow(cs);
}

int CTextureView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	CWnd *pFrame = GetParent();
	if (!m_wndDlgBar.Create(pFrame,IDD_TEXTURE_PROPERTIES,CBRS_LEFT|CBRS_TOOLTIPS|CBRS_FLYBY,0))
	{
		return false;
	}

	return 0;
}

void CTextureView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
{	
	CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}

/*******************************************************************************
/* function name: OnInitialUpdate
/* description: Called when window is displayed for the first time, 
/*	set up window size and position
/*******************************************************************************/
void CTextureView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	CRect rc;
	m_wndDlgBar.GetClientRect(&rc);

	rc.left +=470;
	rc.right +=490;
	rc.bottom =580;
	CWnd *pWnd = GetParent();
	pWnd->MoveWindow(rc);
}

/*******************************************************************************
/* function name: OnUpdate
/* description: Called when hosted documents are updated
/*******************************************************************************/
void CTextureView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();

	Stuff::Page *pPage = NULL;
	Image *pImage = NULL;

	// If we only have one item then select it
	if (pDoc->GetCount() == 1)
	{
		pPage = pDoc->GetPage(0);
		pImage = pDoc->GetImage(0);
	}

	CEdit *pAliasEdit = (CEdit *)m_wndDlgBar.GetDlgItem(IDC_EDIT_ALIASNAME);
	pAliasEdit->SetWindowText("");
	CEdit *pEdit = (CEdit *)m_wndDlgBar.GetDlgItem(IDC_EDIT_PAGENAME);
	pEdit->SetWindowText("");
	CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
	pList->ResetContent();

	//Fill in the page properties list
	if (pPage)
	{
		CString pagename = pPage->GetName();
		pEdit->SetWindowText(pagename);
		
		CString str;
		Stuff::Page::NoteIterator *notes = pPage->MakeNoteIterator();
		Stuff::Note *note;
		while (NULL != (note = notes->ReadAndNext()))
		{
			const char *entry;
			CString name = note->GetName();
			note->GetEntry(&entry);
			
			str.Format("%s=%s",name,entry);
			int index = pList->AddString(str);
			pList->SetItemData(index,(DWORD)note);
			
			if (0==stricmp(name,"alias"))
			{
				pAliasEdit->SetWindowText(entry);
			}
		}
		delete notes;
		
		if (NULL == pHint)
			pList->SetCurSel(0);
		else {
			CPtrList* list = (CPtrList*)pHint;
			Stuff::Note* note = (Stuff::Note*)list->GetHead();
			CString name = note->GetName();
			name.MakeLower();
			int index = pList->FindString(0, name);
			pList->SetCurSel(index);
		}
	}
	else
	{
		// Display comparison of all pages
		CMapStringToString map;
		CMapStringToString mapRef;
		
		for (int x=0;x<pDoc->GetCount();x++)
		{
			Stuff::Page *page = pDoc->GetPage(x);
			Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
			Stuff::Note *note;
			while (NULL != (note = notes->ReadAndNext()))
			{
				const char *entry;
				CString name = note->GetName();
				note->GetEntry(&entry);
				
				name.MakeLower();
				CString value;
				if (map.Lookup(name,value))
				{
					mapRef[name] = "yes";
					if (value.CompareNoCase(entry)==0)
					{
						// Use this value
					}
					else
					{
						map[name] = "";
					}
				}
				else
				{
					if (x==0)
						map[name] = entry;
				}
			}
			delete notes;
		}
		
		POSITION pos = map.GetStartPosition();
		while (pos)
		{
			CString key,value;
			map.GetNextAssoc(pos,key,value);
			if (mapRef[key] == "yes") {
				CString str;
				str.Format("%s=%s",key,value);
				pList->AddString(str);
			}
		}
	}
	OnSelchangeListPage();
}

/*******************************************************************************
/* function name: OnAdd
/* description: Pop up a list of possible entries to added to the hint page
/*******************************************************************************/
void CTextureView::OnAdd() 
{
	CMenu *pMenu = AfxGetMainWnd()->GetMenu();
	CMenu *pSubMenu = pMenu->GetSubMenu(3);
	pSubMenu = pSubMenu->GetSubMenu(0);
	CRect rc;
	m_wndDlgBar.GetDlgItem(IDC_ADD)->GetWindowRect(&rc);
	CPoint point;
	point.x = rc.right;
	point.y = rc.top;

	pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x, point.y, this, NULL);
}

/*******************************************************************************
/* function name: OnDelete
/* description: Delete seleted entries from the hint page
/*******************************************************************************/
void CTextureView::OnDelete() 
{
	CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
	int index = pList->GetCurSel();
	if (index < 0)
		return;

	CString str;
	pList->GetText(index, str);
	str = str.Left(str.Find("="));
	pList->DeleteString(index);

	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();
	int count = pDoc->GetCount();
	for (int x=0;x<count;x++)
	{
		
		Stuff::Page *page = pDoc->GetPage(x);		
		CString str1 = str;
		str1.MakeLower();
		CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
		CString value;
		if (pApp->m_mapHintParams.Lookup(str1,value))
		{
			if (value.GetLength())
			{
				page->DeleteNote(str);				
				pDoc->UpdateAllViews(NULL);
			}
		}
	}
}

/*******************************************************************************
/* function name: OnSelchangeListPage
/* description: Highlight in the entry list has changed, update the list of 
/*	possible entry values
/*******************************************************************************/
void CTextureView::OnSelchangeListPage() 
{	
	CComboBox *pCombo = (CComboBox *)m_wndDlgBar.GetDlgItem(IDC_COMBO_VALUE);
	pCombo->ResetContent();

	CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
	int index = pList->GetCurSel();
	if (index>=0)
	{
		CString notename;
		CString entry;
		Stuff::Note *note = (Stuff::Note *)pList->GetItemData(index);
		if (note)
		{
			Check_Object(note);

			notename = note->GetName();
			notename.MakeLower();

			const char *e;
			note->GetEntry(&e);
			entry = e;
		}
		else
		{
			pList->GetText(index,notename);
			int i = notename.Find('=');
			if (i>=0)
			{
				entry = notename;
				entry.Delete(0,i+1);
				notename = notename.Left(i);

			}
		}

		CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
		CString value;
		if (pApp->m_mapHintParams.Lookup(notename,value))
		{
			while (value.GetLength())
			{
				CString addstr;
				int i = value.Find('|');
				if (i>=0)
				{
					addstr = value.Left(i);
					value.Delete(0,i+1);
				}
				else
				{
					addstr = value;
					value.Empty();
				}
				int index = pCombo->AddString(addstr);
				if (0==stricmp(entry,addstr))
				{
					pCombo->SetCurSel(index);
				}
			}
		}
	}
}

/*******************************************************************************
/* function name: OnSelendokComboValue
/* description: User selects a value for the highlight entry
/*******************************************************************************/
void CTextureView::OnSelendokComboValue() 
{
	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();
	CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
	int index = pList->GetCurSel();
	Stuff::Note *note = (Stuff::Note *)pList->GetItemData(index);

	CComboBox *pCombo = (CComboBox *)m_wndDlgBar.GetDlgItem(IDC_COMBO_VALUE);
	index = pCombo->GetCurSel();
	if (CB_ERR != index)
	{
		CString str;
		CString selname;
		pCombo->GetLBText(index,str);
		if (note)
		{
			note->SetEntry(str);
			selname = note->GetName();
		}
		else
		{
			CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
			int x = pList->GetCurSel();
			CString name;
			pList->GetText(x,name);
			x = name.Find('=');
			if (x>=0)
			{
				name = name.Left(x);
			}

			selname = name;

			for (x=0;x<pDoc->GetCount();x++)
			{
				Stuff::Page *page = pDoc->GetPage(x);
				page->SetEntry(name,str);
			}
		}
		pDoc->UpdateAllViews(NULL);

		CListBox *pList = (CListBox *)m_wndDlgBar.GetDlgItem(IDC_LIST_PAGE);
		for (int x=0;x<pList->GetCount();x++)
		{
			pList->GetText(x,str);
			int i = str.Find('=');
			if (i>0)
			{
				str = str.Left(i);
			}
			if (str.CompareNoCase(selname)==0) {
				pList->SetCurSel(x);
				OnSelchangeListPage();
			}
		}
	}
}

/*******************************************************************************
/* function name: OnAddMenuItems
/* description: Add seleted entry to the hint page with default value set
/*******************************************************************************/
void CTextureView::OnAddMenuItems(UINT nID) 
{
	CMenu *pMenu = AfxGetMainWnd()->GetMenu();
	CMenu *pSubMenu = pMenu->GetSubMenu(3);
	pSubMenu = pSubMenu->GetSubMenu(0);
	CString str;
	pSubMenu->GetMenuString(nID,str,MF_BYCOMMAND);

	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();
	int count = pDoc->GetCount();
	for (int x=0;x<count;x++)
	{
		
		Stuff::Page *page = pDoc->GetPage(x);
		CStringList list;
		Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
		Stuff::Note *note;
		while ((note = notes->ReadAndNext()) != NULL)
		{
			CString name = note->GetName();
			name.MakeLower();
			list.AddTail(name);
		}
		delete notes;
		
		CString str1 = str;
		str1.MakeLower();
		if (list.Find(str1))
			continue;
		
		// We now have a valid entry called str that we want to add
		CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
		
		// Get the default value (first in list)
		CString value = pApp->m_mapHintParams[str1];
		int index = value.Find('|');
		
		// Add to the file
		if (index>=0)
		{
			value = value.Left(index);
			note = page->AddNote(str);
			note->SetEntry(value);
			
			CPtrList list;
			list.AddHead((LPVOID)note);
			pDoc->UpdateAllViews(NULL,0,&list);
		}
	}
}

/*******************************************************************************
/* function name: OnApply
/* description: Change the hint page name, and rename the texture file name
/*******************************************************************************/
void CTextureView::OnApply() 
{
	CEdit *pEdit = (CEdit *)m_wndDlgBar.GetDlgItem(IDC_EDIT_PAGENAME);
	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();

	// Only doable if only one hint it selected
	if (pDoc->GetCount() == 1)
	{
		Stuff::Page* page = pDoc->GetPage(0);
		if (page)
		{
			Stuff::NotationFile *pFile = page->GetNotationFile();

			CString newname;
			pEdit->GetWindowText(newname);
			Stuff::Page *newpage = pFile->FindPage(newname);
			if (NULL != newpage)
			{
				CString str;
				str.Format("%s Already Exists",newname);
				MessageBox(str,"Rename",MB_OK);
				return;
			}
			newpage = pFile->AddPage(newname);

			Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
			Stuff::Note *note;
			while (NULL != (note = notes->ReadAndNext()))
			{
				const char *entry;
				CString name = note->GetName();
				note->GetEntry(&entry);

				newpage->AppendEntry(name,entry);
			}
			delete notes;

			// Rename the texture file
			if (::gos_DoesFileExist(CString("content\\textures\\")+page->GetName()+".png"))
				if (IDYES == MessageBox("Do you want to rename the texture file?",newpage->GetName(),MB_YESNO))
					::gos_RenameFile(CString("content\\textures\\")+page->GetName()+".png",
						CString("content\\textures\\")+newpage->GetName()+".png");
			else if (::gos_DoesFileExist(CString("content\\textures\\")+page->GetName()+".tga"))
				if (IDYES == MessageBox("Do you want to rename the texture file?",newpage->GetName(),MB_YESNO))
					::gos_RenameFile(CString("content\\textures\\")+page->GetName()+".tga",
						CString("content\\textures\\")+newpage->GetName()+".tga");
		

			pFile->DeletePage(page->GetName());
			pDoc->ReplacePage(page,newpage);
			pDoc->UpdateAllViews(NULL);

			// Refresh all the build files views
			CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
			pApp->RefreshFiles();
		}
	}
}

extern bool g_bWarnDuplicateAlias;
/*******************************************************************************
/* function name: OnApplyAlias
/* description: Change the alias name
/*******************************************************************************/
void CTextureView::OnApplyAlias() 
{
	CEdit *pEdit = (CEdit *)m_wndDlgBar.GetDlgItem(IDC_EDIT_ALIASNAME);
	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();

	// Only doable if only one hint it selected
	if (pDoc->GetCount() == 1)
	{
		Stuff::Page* page = pDoc->GetPage(0);
		if (page)
		{
			CString str;
			pEdit->GetWindowText(str);
			if (str.GetLength())
			{
				page->SetEntry("Alias",str);
				page->SetEntry("Resourcify","false");
				Stuff::NotationFile *pFile = page->GetNotationFile();
				Check_Object(pFile);
				Stuff::Page *aliasPage = pFile->FindPage(str);
				if (!aliasPage)
				{
					if (IDYES == MessageBox("Do you want to create the alias hint page?",str,MB_YESNO))
					{
						aliasPage = pFile->SetPage(str);
					}
				}
				
				// Reload the texture image
				if (pDoc->GetCount() == 1)
				{
					pDoc->SetImage(pDoc->LoadTexture(page), 0);
				}

			}
			else
			{
				page->DeleteNote("Alias");
				page->SetEntry("Resourcify","true");
			}

			pDoc->UpdateAllViews(NULL);
		
			// Refresh all the build files views
			g_bWarnDuplicateAlias = true;
			CMultitronApp *pApp = (CMultitronApp *)AfxGetApp();
			pApp->RefreshFiles();
		}
	}
}

/*******************************************************************************
/* function name: OnUpdateUI
/* description: 
/*******************************************************************************/
void CTextureView::OnUpdateUI(CCmdUI* pCmdUI)
{
	CTextureDoc* pDoc = (CTextureDoc *)GetDocument();
	pCmdUI->Enable(pDoc->GetCount() == 1);
}