/*
**	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/>.
*/

/*********************************************************************************************** 
 ***                            Confidential - Westwood Studios                              *** 
 *********************************************************************************************** 
 *                                                                                             * 
 *                 Project Name : Installer                                                    * 
 *                                                                                             * 
 *                     $Archive:: /Commando/Code/Installer/CopyDialog.cpp $* 
 *                                                                                             * 
 *                      $Author:: Ian_l                   $* 
 *                                                                                             * 
 *                     $Modtime:: 1/12/02 7:32p                 $* 
 *                                                                                             * 
 *                    $Revision:: 15                    $* 
 *                                                                                             * 
 *---------------------------------------------------------------------------------------------* 
 * Functions:                                                                                  * 
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

// Includes.
#include "CopyDialog.h"
#include "AssetMgr.h"
#include "Camera.h"
#include "DialogControl.h"
#include "DialogMgr.h"
#include "DialogText.h"
#include "ErrorHandler.h"
#include "Hanim.h"
#include "Installer.h"
#include "Light.h"
#include "MenuBackdrop.h"
#include "Resource.h"
#include "Scene.h"
#include "Translator.h"
#include "ViewerCtrl.h"
#include "Ww3D.h"
#include "WWAudio.h"


// Defines.
#define MODEL_COUNT			13 
#define MODEL_DISPLAY_TIME	22000		// Display time for each model (in milliseconds).


// Static data.
static const char	*_ModelNames [MODEL_COUNT] = {"C_AG_GDI_MG",
																"C_AG_GDI_MGO",
																"C_AG_NOD_MG",
																"C_AG_GDI_LOCKE",
																"C_AG_NOD_SAKU",
																"IGM_PIST",
																"IGM_SNIP",
																"IGM_C4-R",
																"VDC_GDI_HUMVEE",
																"V_GDI_MEDTNK",
																"V_NOD_TURRET",
																"V_GDI_ORCA",
																"ENC_GPWR"
															  };

	
static const char	*_AnimNames [MODEL_COUNT]  = {"S_A_HUMAN.H_A_A0A1",
																"S_A_HUMAN.H_A_A0B1",
																"S_A_HUMAN.H_A_A0A1",
																"S_A_HUMAN.H_A_A0B1",
																"S_B_HUMAN.H_B_A0A0_13",
																"",
																"",
																"",
																"",
																"",
																"",
																"V_GDI_ORCA.V_GDI_ORCA",
																""
															  };

static const int _ModelHeadings [MODEL_COUNT] =	{IDS_GDI_SOLDIER_HEADING,
																 IDS_GDI_OFFICER_HEADING,
																 IDS_NOD_SOLDIER_HEADING,
																 IDS_LOCKE_HEADING,
																 IDS_SAKURA_HEADING,
																 IDS_PISTOL_HEADING,
																 IDS_SNIPER_RIFLE_HEADING,
																 IDS_REMOTE_C4_HEADING,
																 IDS_GDI_HUMM_VEE_HEADING,
																 IDS_GDI_MEDIUM_TANK_HEADING,
																 IDS_NOD_TURRET_HEADING,
																 IDS_GDI_ORCA_HEADING,
																 IDS_GDI_POWER_PLANT_HEADING
																};

static const int _ModelDescriptions [MODEL_COUNT] = {IDS_GDI_SOLDIER_DESCRIPTION,
																	  IDS_GDI_OFFICER_DESCRIPTION,
																	  IDS_NOD_SOLDIER_DESCRIPTION,
																	  IDS_LOCKE_DESCRIPTION,
																	  IDS_SAKURA_DESCRIPTION,
																	  IDS_PISTOL_DESCRIPTION,
																	  IDS_SNIPER_RIFLE_DESCRIPTION,
																	  IDS_REMOTE_C4_DESCRIPTION,
																	  IDS_GDI_HUMM_VEE_DESCRIPTION,
																	  IDS_GDI_MEDIUM_TANK_DESCRIPTION,
																	  IDS_NOD_TURRET_DESCRIPTION,
																	  IDS_GDI_ORCA_DESCRIPTION,
																	  IDS_GDI_POWER_PLANT_DESCRIPTION
																	 };

																	  
/***********************************************************************************************
 * CopyDialogClass::CopyDialogClass --																			  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
CopyDialogClass::CopyDialogClass()
	: InstallMenuDialogClass (IDD_DIALOG_COPY),
	  SupplementalModel (NULL),
	  ProgressBarModel (NULL),
	  ProgressBarAnim (NULL),
	  CurrentModel (0),
	  CountdownTimer (NULL),
	  FlashTimer (NULL),
	  FileSystemErrorPopup (NULL),
	  AddedModels (false)
{
}


/***********************************************************************************************
 * CopyDialogClass::On_Init_Dialog --																			  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::On_Init_Dialog (void)
{
	WideStringClass sourcepath;

	ViewerCtrlClass *viewercontrol = Get_Dlg_Item (IDC_COPY_VIEWER)->As_ViewerCtrlClass();
	
	// Disable the OK button until copying is complete.
	Enable_Dlg_Item (IDOK, false);

	// Configure the W3D elements.
	viewercontrol->Set_Background_Visible (false);
	Add_Models();

	// Start the copy thread.
	CopyThread = new CopyThreadClass (_Installer.Get_Total_Size (false));
	CopyThread->Execute();

	CountdownTimer = new CDTimerClass <SafeTimerClass> (MODEL_DISPLAY_TIME);

	InstallMenuDialogClass::On_Init_Dialog();
}


/***********************************************************************************************
 * CopyDialogClass::On_Activate --																				  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::On_Activate (bool onoff)
{
	if (onoff) {
		AIL_set_preference (DIG_DS_MIX_FRAGMENT_CNT, 64);
		AIL_serve();
	} else {
		AIL_set_preference (DIG_DS_MIX_FRAGMENT_CNT, 8);
	}

	InstallMenuDialogClass::On_Activate (onoff);
}


/***********************************************************************************************
 * CopyDialogClass::On_Frame_Update --																			  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::On_Frame_Update (void)
{
	WideStringClass  statusmessage;
	DialogTextClass *statustext1, *statustext2;

	// Set both status lines with the status message. By default, use the small text for display.
	CopyThread->Get_Status_Message (statusmessage);
	statustext1 = Get_Dlg_Item (IDC_COPY_STATUS1)->As_DialogTextClass();
	statustext2 = Get_Dlg_Item (IDC_COPY_STATUS2)->As_DialogTextClass();

	// Update the copy status.
	switch (CopyThread->Get_Status()) {

		case CopyThreadClass::STATUS_OK:
		{
			float	fraction, framecount;
			char  percentagestring [10];

			Add_Models();

 			// Advance to next model if timer has 'gone off'.
			if (CountdownTimer->Value() == 0) {
				CurrentModel = (CurrentModel + 1) % MODEL_COUNT;
				Set_Model (CurrentModel);	
		 		delete CountdownTimer;
				CountdownTimer = new CDTimerClass <SafeTimerClass> (MODEL_DISPLAY_TIME);
			}
			
			// Update the progress bar.
			statustext1->Set_Text (statusmessage);
			statustext2->Set_Text (L"");
			framecount = ProgressBarModel->Peek_Animation()->Get_Num_Frames();
			fraction = CopyThread->Get_Fraction_Complete();
			ProgressBarModel->Set_Animation (ProgressBarAnim, fraction * (framecount - 1), RenderObjClass::ANIM_MODE_MANUAL);
			percentagestring [sizeof (percentagestring) - 1] = '\0';
			_snprintf (percentagestring, sizeof (percentagestring) - 1, "%u%%", (unsigned) (fraction * 100.0f));
			Set_Dlg_Item_Text (IDC_COPY_PERCENTAGE, WideStringClass (percentagestring));
			break;
		}

		case CopyThreadClass::STATUS_ERROR:
			FileSystemErrorPopup = MessageBoxClass::Create_Dialog (TxWideStringClass (IDS_APPLICATION_ERROR), TxWideStringClass (IDS_FILE_SYSTEM_ERROR), MessageBoxClass::MESSAGE_BOX_TYPE_RETRY_QUIT, this);
			CountdownTimer->Stop();
			break;

		case CopyThreadClass::STATUS_SUCCESS:

			Remove_Models();
			
 			// Advance to next model if timer has 'gone off'.
			if (CountdownTimer->Value() == 0) {
				CurrentModel = (CurrentModel + 1) % MODEL_COUNT;
				Set_Model (CurrentModel);	
		 		delete CountdownTimer;
				CountdownTimer = new CDTimerClass <SafeTimerClass> (MODEL_DISPLAY_TIME);
			}

			if (FlashTimer == NULL) {
				
				FlashTimer = new TTimerClass <SafeTimerClass>;

				// Allow the user to continue by enabling the OK button.
				Enable_Dlg_Item (IDOK, true);
			}

			// Flash the status message in large text.
			statustext1->Set_Text (L"");
			Set_Dlg_Item_Text (IDC_COPY_PERCENTAGE, L"");
			if (((FlashTimer->Value() / 1000) % 3) == 0) {
				statustext2->Set_Text (statusmessage);
			} else {
				statustext2->Set_Text (L"");
			}
			break;

		case CopyThreadClass::STATUS_ABORTED:

			Remove_Models();

			// Use the large text to display the status message.
			statustext1->Set_Text (L"");
			statustext2->Set_Text (statusmessage);

			// Cancel this dialog if the copy thread has terminated.
			if (!CopyThread->Is_Running()) {
				
				MenuDialogClass::On_Command (IDCANCEL, 0, 0);
			
				// NOTE: Must return because this object may have already been deleted.
				return;
			}
			break;

		case CopyThreadClass::STATUS_FAILURE:
		{
			WideStringClass errormessage;

			// A fatal error has occurred.
			CopyThread->Get_Error_Message (errormessage);
			throw (errormessage);	
		}

		default:
			break;
	}

	InstallMenuDialogClass::On_Frame_Update();
}


/***********************************************************************************************
 * CopyDialogClass::Add_Models --																				  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::Add_Models()
{
	if (!AddedModels) {

		const char *supplementalmodelname = "IN_COPYGIZMO";
		const char *supplementalanimname  = "IN_COPYGIZMO.IN_COPYGIZMO";
		const char *progressbarmodelname  = "IN_PROGRESS";
		const char *progressbaranimname	 = "IN_PROGRESS.IN_PROGRESS";

		HAnimClass *supplementalanim;

		SupplementalModel = WW3DAssetManager::Get_Instance()->Create_Render_Obj (supplementalmodelname);
		if (SupplementalModel != NULL) {
			Get_BackDrop()->Peek_Scene()->Add_Render_Object (SupplementalModel);

			supplementalanim = WW3DAssetManager::Get_Instance()->Get_HAnim (supplementalanimname);
			if (supplementalanim != NULL) {
				SupplementalModel->Set_Animation (supplementalanim, 0, RenderObjClass::ANIM_MODE_LOOP);
				REF_PTR_RELEASE (supplementalanim);
			}
		}

		ProgressBarModel = WW3DAssetManager::Get_Instance()->Create_Render_Obj (progressbarmodelname);
		if (ProgressBarModel != NULL) {
			Get_BackDrop()->Peek_Scene()->Add_Render_Object (ProgressBarModel);
			ProgressBarAnim = WW3DAssetManager::Get_Instance()->Get_HAnim (progressbaranimname);
			if (ProgressBarAnim != NULL) {
				ProgressBarModel->Set_Animation (ProgressBarAnim, 0, RenderObjClass::ANIM_MODE_MANUAL);
			}
		}

		Set_Model (CurrentModel);
		
		AddedModels = true;	
	}
}


/***********************************************************************************************
 * CopyDialogClass::Set_Model --																					  *	
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::Set_Model (unsigned modelindex)
{
	const float	rotationrate = 45.0f;	

	// Set the appropriate model, animation and interface for the viewer.
	
	ViewerCtrlClass *viewercontrol = Get_Dlg_Item (IDC_COPY_VIEWER)->As_ViewerCtrlClass();

	Set_Dlg_Item_Text (IDC_COPY_HEADER, TxWideStringClass (_ModelHeadings [modelindex]));
	Set_Dlg_Item_Text (IDC_COPY_DESCRIPTION, TxWideStringClass (_ModelDescriptions [modelindex]));

	viewercontrol->Set_Model (_ModelNames [modelindex]);
	viewercontrol->Set_Animation (_AnimNames [modelindex]);
	viewercontrol->Set_Interface_Mode (ViewerCtrlClass::Z_ROTATION, rotationrate);
		
	//	Traverse the model...
	for (int index = 0; index < viewercontrol->Peek_Model()->Get_Num_Sub_Objects(); index++) {

		RenderObjClass *sub_obj = viewercontrol->Peek_Model()->Get_Sub_Object (index);

		// Hide muzzle flashes - they are not appropriate in this context.
		if (::strstr (sub_obj->Get_Name(), "MUZZLEFLASH") != NULL)  {
			sub_obj->Set_Hidden (true);
		}

		// Hide flares - the rendering system has not been initialized.
		if (sub_obj->Class_ID() == RenderObjClass::CLASSID_DAZZLE) {
			sub_obj->Set_Hidden (true);
		}

		REF_PTR_RELEASE (sub_obj);
	}
}


/***********************************************************************************************
 * CopyDialogClass::Remove_Models --																			  *	
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::Remove_Models()
{
	if (AddedModels) {
		REF_PTR_RELEASE (ProgressBarAnim);
		ProgressBarModel->Remove();
		REF_PTR_RELEASE (ProgressBarModel);
		SupplementalModel->Remove();
		REF_PTR_RELEASE (SupplementalModel);

		AddedModels = false;
	}
}


/***********************************************************************************************
 * CopyDialogClass::End_Dialog --																				  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::End_Dialog (void)
{
	Remove_Models();

	// Wait for copy thread to terminate (in case it hasn't finished yet).
	while (CopyThread->Is_Running()) {
		Sleep (50);
	}
	delete CopyThread;

	AIL_set_preference (DIG_DS_MIX_FRAGMENT_CNT, 8);

	if (CountdownTimer != NULL) delete CountdownTimer;
	if (FlashTimer != NULL) delete FlashTimer;

	InstallMenuDialogClass::End_Dialog();
}


/***********************************************************************************************
 * CopyDialogClass::Callback --																					  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::Callback (int id, PopupDialogClass *popup)
{
 	if (popup == FileSystemErrorPopup) {

 		switch (id) {

 			case IDC_BUTTON_RETRY:
 				CopyThread->Set_Status (CopyThreadClass::STATUS_RETRY);
 				REF_PTR_RELEASE (popup);
				CountdownTimer->Start();
				break;

 			case IDC_BUTTON_QUIT:
 				CopyThread->Set_Status (CopyThreadClass::STATUS_QUIT);
 				REF_PTR_RELEASE (popup);
				CountdownTimer->Start();
				break;
				
 			default:
 				break;
		}

	} else {
			
		switch (id) {
		
			case IDC_BUTTON_YES:
				CopyThread->Set_Abort (true);
				CountdownTimer->Start();
				break;

			case IDC_BUTTON_NO:
			case IDCANCEL:
			case IDOK:
				CopyThread->Set_Abort (false);
				CountdownTimer->Start();
				break;

			default:
				break;
		}
	}

	// NOTE: Do not call base callback - this function replaces base callback functionality.
}


/***********************************************************************************************
 * CopyDialogClass::On_Command --																				  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/22/01    IML : Created.                                                                * 
 *=============================================================================================*/
void CopyDialogClass::On_Command (int ctrl_id, int message_id, DWORD param)
{
	switch (ctrl_id) {

		case IDOK:

			// If the OK button has been disabled throw away this message.
			if (!Is_Dlg_Item_Enabled (IDOK)) return;
			break;

		case IDCANCEL:

			// If the copy process has already finished then cancel immediately.
			if (!CopyThread->Is_Running()) {
				MenuDialogClass::On_Command (IDCANCEL, 0, 0);
				return;
			} else {
			
				// Can the user cancel?
				// NOTE: User will not be able to cancel if the copying process is uninterruptable because,
				//			for example, it is updating the registry.
				if (!CopyThread->Can_Abort (true)) {
					CopyThread->Set_Abort (false);
					return;
				}
				CountdownTimer->Stop();
			}

 		default:
			break;
	}
	
	InstallMenuDialogClass::On_Command (ctrl_id, message_id, param);
}
