/*
**	Command & Conquer Renegade(tm)
**	Copyright 2025 Electronic Arts Inc.
**
**	This program is free software: you can redistribute it and/or modify
**	it under the terms of the GNU General Public License as published by
**	the Free Software Foundation, either version 3 of the License, or
**	(at your option) any later version.
**
**	This program is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**	GNU General Public License for more details.
**
**	You should have received a copy of the GNU General Public License
**	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/***********************************************************************************************
 ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
 ***********************************************************************************************
 *                                                                                             *
 *                 Project Name : LevelEdit                                                    *
 *                                                                                             *
 *                     $Archive:: /Commando/Code/Tools/LevelEdit/IncludeFilesDialog.cpp                                                                                                                                                                                                                                                                                                                                          $Modtime::                                                             $*
 *                                                                                             *
 *                    $Revision:: 3                                                           $*
 *                                                                                             *
 *---------------------------------------------------------------------------------------------*
 * Functions:                                                                                  *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */


#include "stdafx.h"
#include "leveledit.h"
#include "includefilesdialog.h"
#include "filemgr.h"
#include "icons.h"
#include "utils.h"


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


/////////////////////////////////////////////////////////////////////////////
//
// IncludeFilesDialogClass
//
IncludeFilesDialogClass::IncludeFilesDialogClass(CWnd* pParent /*=NULL*/)
	: m_hGlobalFolder (NULL),
	  m_hLevelFolder (NULL),
	  m_CurrentItem (NULL),
	  CDialog(IncludeFilesDialogClass::IDD, pParent)
{
	//{{AFX_DATA_INIT(IncludeFilesDialogClass)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT

	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
void
IncludeFilesDialogClass::DoDataExchange (CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(IncludeFilesDialogClass)
	DDX_Control(pDX, IDC_INCLUDE_TREE, m_IncludesTreeCtrl);
	//}}AFX_DATA_MAP
	return ;
}


BEGIN_MESSAGE_MAP(IncludeFilesDialogClass, CDialog)
	//{{AFX_MSG_MAP(IncludeFilesDialogClass)
	ON_NOTIFY(TVN_SELCHANGED, IDC_INCLUDE_TREE, OnSelchangedIncludeTree)
	ON_EN_CHANGE(IDC_SPEC_EDIT, OnChangeSpecEdit)
	ON_BN_CLICKED(IDC_ADD_REMOVE_BUTTON, OnAddRemoveButton)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
BOOL
IncludeFilesDialogClass::OnInitDialog (void)
{
	// Allow the base class to process this message
	CDialog::OnInitDialog ();	

	// Insert the 2 main folders into the tree control
	m_IncludesTreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
	m_hGlobalFolder = m_IncludesTreeCtrl.InsertItem ("Global", FOLDER_ICON, FOLDER_ICON);
	m_hLevelFolder = m_IncludesTreeCtrl.InsertItem ("Level Specific", FOLDER_ICON, FOLDER_ICON);

	// Ensure the file manager has the latest and greatest
	::Get_File_Mgr ()->Build_Global_Include_List ();
	
	// Loop through all the global include files and add them to the tree control
	DynamicVectorClass<CString> &global_list = ::Get_File_Mgr ()->Get_Global_Include_File_List ();
	for (int index = 0; index < global_list.Count (); index ++) {
		int icon_index = (::strpbrk (global_list[index], "*?") != NULL) ? FILES_ICON : FILE_ICON;
		m_IncludesTreeCtrl.InsertItem (global_list[index], icon_index, icon_index, m_hGlobalFolder);
	}
	
	// Loop through all the level-specific include files and add them to the tree control
	DynamicVectorClass<CString> &level_list = ::Get_File_Mgr ()->Get_Include_File_List ();
	for (index = 0; index < level_list.Count (); index ++) {
		int icon_index = (::strpbrk (level_list[index], "*?") != NULL) ? FILES_ICON : FILE_ICON;
		m_IncludesTreeCtrl.InsertItem (level_list[index], icon_index, icon_index, m_hLevelFolder);
	}
	
	// Create the file picker control
	CRect rect;
	HWND hold_edit = ::GetDlgItem (m_hWnd, IDC_SPEC_EDIT);
	::GetWindowRect (hold_edit, &rect);
	ScreenToClient (&rect);
	m_FilePicker.Create_Picker (WS_CHILD | WS_TABSTOP | WS_VISIBLE,
										 rect,
										 this,
										 IDC_SPEC_EDIT);
	
	::SetWindowPos (m_FilePicker, ::GetDlgItem (m_hWnd, IDC_SPEC_STATIC), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
	::DestroyWindow (hold_edit);

	// Ensure the file specs are sorted
	m_IncludesTreeCtrl.SortChildren (m_hGlobalFolder);
	m_IncludesTreeCtrl.SortChildren (m_hLevelFolder);
	m_IncludesTreeCtrl.SelectItem (m_hGlobalFolder);
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
void
IncludeFilesDialogClass::OnOK (void)
{
	DynamicVectorClass<CString> &global_list = ::Get_File_Mgr ()->Get_Global_Include_File_List ();
	DynamicVectorClass<CString> &level_list = ::Get_File_Mgr ()->Get_Include_File_List ();
	global_list.Delete_All ();
	level_list.Delete_All ();

	// Loop through all the children of the global folder	
	for (HTREEITEM hchild = m_IncludesTreeCtrl.GetChildItem (m_hGlobalFolder);
		  hchild != NULL;
		  hchild = m_IncludesTreeCtrl.GetNextSiblingItem (hchild)) {
		
		// Add this filespec to the global list
		CString child_text = m_IncludesTreeCtrl.GetItemText (hchild);
		global_list.Add (child_text);
	}

	// Loop through all the children of the level-specific folder
	for (hchild = m_IncludesTreeCtrl.GetChildItem (m_hLevelFolder);
		  hchild != NULL;
		  hchild = m_IncludesTreeCtrl.GetNextSiblingItem (hchild)) {
		
		// Add this filespec to the local list
		CString child_text = m_IncludesTreeCtrl.GetItemText (hchild);
		level_list.Add (child_text);
	}

	// Check the latest copy of the global include file list into the VSS
	::Get_File_Mgr ()->Update_Global_Include_File_List ();

	// Allow the base class to process this message
	CDialog::OnOK ();
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// OnSelchangedIncludeTree
//
void
IncludeFilesDialogClass::OnSelchangedIncludeTree
(
	NMHDR *pNMHDR,
	LRESULT *pResult
)
{
	NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;
	(*pResult) = 0;
	
	// Change the text in the edit control to reflect the new selection
	HTREEITEM hitem = m_IncludesTreeCtrl.GetSelectedItem ();	
	if (m_IncludesTreeCtrl.GetParentItem (hitem) != NULL) {		
		
		// Put the file spec into the edit control
		CString path = m_IncludesTreeCtrl.GetItemText (hitem);
		SetDlgItemText (IDC_SPEC_EDIT, path);
		SetDlgItemText (IDC_ADD_REMOVE_BUTTON, "&Remove");
		m_CurrentItem = hitem;

		// Let the file picker know the full path to the file
		path = ::Get_File_Mgr ()->Make_Full_Path (path);
		m_FilePicker.Set_Default_Filename (path);

	} else {
		//SetDlgItemText (IDC_SPEC_EDIT, "");
		SetDlgItemText (IDC_ADD_REMOVE_BUTTON, "&Add");
		m_CurrentItem = NULL;
	}

	// Ensure the 'add/remove' button is correctly enabled/disabled
	//::EnableWindow (::GetDlgItem (m_hWnd, IDC_ADD_REMOVE_BUTTON), enable_button);

	// Refresh the state of the 'add/remove' button
	//Update_Add_Remove_Button ();
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// Update_Add_Remove_Button
//
void
IncludeFilesDialogClass::Update_Add_Remove_Button (void)
{
	CString filespec;
	GetDlgItemText (IDC_SPEC_EDIT, filespec);
	filespec = ::Get_File_Mgr ()->Make_Relative_Path (filespec);

	// Determine which item to use as a parent
	HTREEITEM hselected_item = m_IncludesTreeCtrl.GetSelectedItem ();	
	HTREEITEM hroot = hselected_item;
	if (m_IncludesTreeCtrl.GetParentItem (hroot) != NULL) {
		hroot = m_IncludesTreeCtrl.GetParentItem (hroot);
	}

	// Change the button text if the entry was found or not
	m_CurrentItem = Find_Spec (filespec, hroot);
	if (m_CurrentItem != NULL) {
		SetDlgItemText (IDC_ADD_REMOVE_BUTTON, "&Remove");

		// Ensure this item is selected in the tree control as well		
		if (hselected_item != m_CurrentItem) {
			m_IncludesTreeCtrl.SelectItem (m_CurrentItem);
			m_IncludesTreeCtrl.EnsureVisible (m_CurrentItem);
		}

	} else {
		SetDlgItemText (IDC_ADD_REMOVE_BUTTON, "&Add");
	}

	return ;
}


////////////////////////////////////////////////////////////////////
//
// Find_Spec
//
HTREEITEM
IncludeFilesDialogClass::Find_Spec
(
	LPCTSTR filespec,
	HTREEITEM hroot
)
{	
	HTREEITEM hitem = NULL;

	// Loop through all the children of the global folder
	for (HTREEITEM hchild = m_IncludesTreeCtrl.GetChildItem (hroot);
		  (hchild != NULL) && (hitem == NULL);
		  hchild = m_IncludesTreeCtrl.GetNextSiblingItem (hchild)) {
		
		// Is this the entry we are looking for?
		CString child_text = m_IncludesTreeCtrl.GetItemText (hchild);
		if (child_text.CompareNoCase (filespec) == 0) {
			hitem = hchild;
		}
	}
	
	// Return the tree item if we found the item
	return hitem;
}


////////////////////////////////////////////////////////////////////
//
// OnChangeSpecEdit
//
void
IncludeFilesDialogClass::OnChangeSpecEdit (void)
{
	Update_Add_Remove_Button ();
	return ;
}


////////////////////////////////////////////////////////////////////
//
// OnAddRemoveButton
//
void
IncludeFilesDialogClass::OnAddRemoveButton (void) 
{
	// Are we adding or removing an entry from the tree control?
	if (m_CurrentItem != NULL) {
		HTREEITEM hnew_sel = m_IncludesTreeCtrl.GetPrevSiblingItem (m_CurrentItem);
		hnew_sel = (hnew_sel != NULL) ? hnew_sel : m_hGlobalFolder;
		m_IncludesTreeCtrl.DeleteItem (m_CurrentItem);
		m_IncludesTreeCtrl.SelectItem (hnew_sel);
		m_IncludesTreeCtrl.EnsureVisible (hnew_sel);
	} else {
		
		// Determine which item to use as a parent
		HTREEITEM hitem = m_IncludesTreeCtrl.GetSelectedItem ();
		if (m_IncludesTreeCtrl.GetParentItem (hitem) != NULL) {
			hitem = m_IncludesTreeCtrl.GetParentItem (hitem);
		}

		// Get the text the user entered
		CString filespec;
		GetDlgItemText (IDC_SPEC_EDIT, filespec);

		// Is the new path valid?
		bool rel_path = ::Is_Path_Relative (filespec);
		if ((rel_path == true) || ((rel_path == false) && ::Get_File_Mgr ()->Is_Path_Valid (filespec))) {

			// Add this entry to the tree control
			CString new_entry = ::Get_File_Mgr ()->Make_Relative_Path (filespec);
			int icon_index = (::strpbrk (new_entry, "*?") != NULL) ? FILES_ICON : FILE_ICON;
			HTREEITEM hnew_item = m_IncludesTreeCtrl.InsertItem (new_entry, icon_index, icon_index, hitem);

			// Now select this new item...
			m_IncludesTreeCtrl.SelectItem (hnew_item);
			m_IncludesTreeCtrl.EnsureVisible (hnew_item);

		} else {
			
			// Let the user know this path is invalid
			CString message;
			CString title;
			message.Format (IDS_INVALID_MODEL_PATH_MSG, (LPCTSTR)::Get_File_Mgr()->Get_Base_Path ());
			title.LoadString (IDS_INVALID_MODEL_PATH_TITLE);
			::MessageBox (m_hWnd, message, title, MB_ICONERROR | MB_OK);
		}				
	}

	// Ensure the file specs are sorted
	m_IncludesTreeCtrl.SortChildren (m_hGlobalFolder);
	m_IncludesTreeCtrl.SortChildren (m_hLevelFolder);
	return ;
}


////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
void
IncludeFilesDialogClass::OnDestroy (void)
{
	m_IncludesTreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
	CDialog::OnDestroy();		
	return ;
}
