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

// EditStringDialog.cpp : implementation file
//

#include "stdafx.h"
#include "leveledit.h"
#include "editstringdialog.h"
#include "translateobj.h"
#include "definitionclassids.h"
#include "presetmgr.h"
#include "preset.h"


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


/////////////////////////////////////////////////////////////////////////////
//	Local prototypes
/////////////////////////////////////////////////////////////////////////////
bool		Is_Valid_ID_Char (char ch);


/////////////////////////////////////////////////////////////////////////////
//
// EditStringDialogClass
//
/////////////////////////////////////////////////////////////////////////////
EditStringDialogClass::EditStringDialogClass(CWnd* pParent /*=NULL*/)
	:	m_Object (NULL),
		CDialog(EditStringDialogClass::IDD, pParent)
{
	//{{AFX_DATA_INIT(EditStringDialogClass)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
EditStringDialogClass::DoDataExchange (CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(EditStringDialogClass)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
	return ;
}


BEGIN_MESSAGE_MAP(EditStringDialogClass, CDialog)
	//{{AFX_MSG_MAP(EditStringDialogClass)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
EditStringDialogClass::OnInitDialog (void) 
{
	CDialog::OnInitDialog ();

	//
	//	Get information about the location where we want to create the
	// sound preset picker control
	//
	HWND placeholder_wnd = ::GetDlgItem (m_hWnd, IDC_SOUND_PRESET_EDIT);
	CRect rect;
	::GetWindowRect (placeholder_wnd, &rect);
	ScreenToClient (&rect);
	::DestroyWindow (placeholder_wnd);

	//
	//	Create the preset picker control
	//
	m_PresetPicker.Create_Picker (WS_CHILD | WS_TABSTOP | WS_VISIBLE, rect, this, 101);
	m_PresetPicker.Set_Read_Only (true);

	//
	//	Configure the preset picker control
	//
	m_PresetPicker.Set_Class_ID (CLASSID_SOUND);	
	if (m_Object != NULL && m_Object->Get_Sound_ID () > 0) {
		PresetClass *preset = PresetMgrClass::Find_Preset (m_Object->Get_Sound_ID ());
		m_PresetPicker.Set_Preset (preset);
	}

	//
	//	Fill in the text controls
	//
	if (m_Object != NULL) {
		CString text = m_Object->Get_English_String ();
		Convert_Newline_To_Chars (text);
		
		SetDlgItemText (IDC_CODEID_EDIT, m_Object->Get_ID_Desc ());
		SetDlgItemText (IDC_STRING_EDIT, text);
		SetDlgItemText (IDC_ANIMATION_NAME_EDIT, m_Object->Get_Animation_Name ());

		//
		//	Select the string so the user can readily modify its contents
		//
		::SetFocus (::GetDlgItem (m_hWnd, IDC_STRING_EDIT));
		SendDlgItemMessage (IDC_STRING_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);

	} else {
		SetDlgItemText (IDC_CODEID_EDIT, "IDS_");
		
		//
		//	Select the CODE ID so the user can enter a valid ID
		//
		::SetFocus (::GetDlgItem (m_hWnd, IDC_CODEID_EDIT));
		SendDlgItemMessage (IDC_CODEID_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
	}
	
	return FALSE;
}


/////////////////////////////////////////////////////////////////////////////
//
// Convert_Newline_To_Chars
//
/////////////////////////////////////////////////////////////////////////////
void
EditStringDialogClass::Convert_Newline_To_Chars (CString &string)
{
	CString retval;

	//
	//	Take a guess as to how large to make the final string
	//
	int count = string.GetLength ();

	//
	//	Copy characters between the strings
	//
	for (int index = 0; index < count; index ++) {
		
		if (string[index] == '\n') {
			retval += "\\n";
		} else if (string[index] == '\t') {
			retval += "\\t";
		} else {
			retval += string[index];
		}
	}

	string = retval;
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// Convert_Chars_To_Newline
//
/////////////////////////////////////////////////////////////////////////////
void
EditStringDialogClass::Convert_Chars_To_Newline (CString &string)
{
	CString retval;
	
	//
	//	Take a guess as to how large to make the final string
	//
	int count = string.GetLength ();
	//retval.GetBufferSetLength (count);

	//
	//	Copy characters between the strings
	//
	for (int index = 0; index < count; index ++) {
		
		if (index + 1 < count && string[index] == '\\' && string[index + 1] == 'n') {
			retval += '\n';
			index ++;
		} else if (index + 1 < count && string[index] == '\\' && string[index + 1] == 't') {
			retval += '\t';
			index ++;
		} else {
			retval += string[index];
		}
	}

	string = retval;
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
EditStringDialogClass::OnOK (void)
{
	if (Validate_ID ()) {
		
		//
		//	Create a new translation object (if necessary)
		//		
		if (m_Object == NULL) {						
			m_Object = new TDBObjClass;
		}

		//
		//	Read the strings the user entered
		//
		CString code_id;
		GetDlgItemText (IDC_CODEID_EDIT, code_id);

		CString text;
		GetDlgItemText (IDC_STRING_EDIT, text);
		Convert_Chars_To_Newline (text);

		CString anim_name;
		GetDlgItemText (IDC_ANIMATION_NAME_EDIT, anim_name);

		//
		//	Pass the new strings onto the translation object
		//
		m_Object->Set_ID_Desc (code_id);
		m_Object->Set_English_String (text);
		m_Object->Set_Animation_Name (anim_name);
		
		//
		//	Pass the sound preset ID onto the translation object
		//
		int sound_id = -1;
		PresetClass *sound_preset = m_PresetPicker.Get_Preset ();
		if (sound_preset != NULL) {
			sound_id = sound_preset->Get_ID ();
		}
		m_Object->Set_Sound_ID (sound_id);
		
		CDialog::OnOK ();
	}
	return ;
}


/////////////////////////////////////////////////////////////////////////////
//
// Validate_ID
//
/////////////////////////////////////////////////////////////////////////////
bool
EditStringDialogClass::Validate_ID (void)
{
	bool retval = false;

	//
	//	Get the string ID from the control
	//
	CString code_id;
	GetDlgItemText (IDC_CODEID_EDIT, code_id);

	//
	//	Validate the ID
	//
	return Validate_String_ID (m_hWnd, code_id);
}


/////////////////////////////////////////////////////////////////////////////
//
// Validate_String_ID
//
/////////////////////////////////////////////////////////////////////////////
bool
Validate_String_ID (HWND wnd, const char *string_id)
{
	bool retval = false;
	CString code_id = string_id;

	if (code_id.GetLength () == 0) {
		
		//
		//	Warn the user they need to enter some ID
		//
		::MessageBox (wnd, "Please enter a descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);

	} else if (code_id.GetLength () < 4) {

		//
		//	Warn the user they should enter a descriptive name
		//
		::MessageBox (wnd, "Code identifier is too short. Please enter a more descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);

	} else if (code_id[0] < 0x41 || code_id[0] > 0x7A || (code_id[0] >= 0x5B && code_id[0] <= 0x60)) {
		
		//
		//	Warn the user the name must start with a character
		//
		::MessageBox (wnd, "The code identifier must begin with a character (not a number), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);

	} else {
		
		//
		//	Check each character in the string to make sure its exceptable
		//
		int count		= code_id.GetLength ();
		bool is_valid	= true;
		for (int index = 1; is_valid && index < count; index ++) {			
			is_valid &= Is_Valid_ID_Char (code_id[index]);
		}

		if (is_valid == false) {
			
			//
			//	Warn the user that the code ID contains an illegal character
			//
			::MessageBox (wnd, "The code identifier can only contain characters (a-z, A-Z), numbers (0-9), and the underscore character (_), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);

		} else {
			retval = true;
		}
	}


	return retval;
}


/////////////////////////////////////////////////////////////////////////////
//
// Is_Valid_ID_Char
//
/////////////////////////////////////////////////////////////////////////////
bool
Is_Valid_ID_Char (char ch)
{
	bool is_valid = false;
	
	//
	//	The character if valid if its either a character, a number, or an underscore
	//
	is_valid |= (ch >= '0' && ch <= '9');
	is_valid |= (ch >= 'A' && ch <= 'Z');
	is_valid |= (ch >= 'a' && ch <= 'z');
	is_valid |= (ch == '_');
	
	return is_valid;
}

