using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Babebi4
{
	public partial class MainForm : Form
	{
		#region		functions

		/// next Word Id
		internal int Word_Pattern__Id__Next(bool t_for_W__f_for_P)
		{
			string tableName = (t_for_W__f_for_P ? "Word" : "Pattern");

			DataTable dataTable = this.DataSet.Tables[tableName];

			int biggestWordId = -1;
			foreach (DataRow dataRow in dataTable.Rows)
			{
				if (dataRow.RowState == DataRowState.Deleted || dataRow.RowState == DataRowState.Detached)
				{
					continue;
				}

				int id = dataRow.Field<int>("Id");

				if (id > biggestWordId)
				{
					biggestWordId = id;
				}
			}

		///	biggestWordId = dataTable.AsEnumerable().Max<DataRow>(dataRow => dataRow.Field<int>("Id"));
			
			return biggestWordId + 1;
		}

		/// Id
		internal void Word_Pattern__Id__TextChanged(bool t_for_W__f_for_P, TextBox_WEM textBox_WEM__Id, ref int id)
		{
			if (textBox_WEM__Id == null)
			{
				return;
			}

			string tableName = (t_for_W__f_for_P ? "Word" : "Pattern");

			DataTable dataTable				= this.DataSet.Tables[tableName];
			DataTable dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];
			
			string idString = textBox_WEM__Id.Text();

			/// empty?
			if (string.IsNullOrEmpty(idString))
			{
				textBox_WEM__Id.SetError("The value of the '" + tableName + " Id' cannot be empty.", "" + tableName + " Id required");

				id = -1;
			}

			/// the user should have copy/paste shit in the Id...
			if (!int.TryParse(idString, out id))
			{
				textBox_WEM__Id.SetError("The value of the '" + tableName + " Id' not a valid Integer.", "Not an integer");

				id = -1;   /// parce qu'il passe à 0 avec le TryParse(...)
			}

			string current__IdString = textBox_WEM__Id.Reference;

			bool the_Id_is_already_existing;

			DataRow alreadyExistingDataRow 
				= dataTable.Rows.Find(id);

			if (alreadyExistingDataRow != null)
			{
				if (current__IdString == null)
				{
					the_Id_is_already_existing = true;
				}
				else
				{
					if (current__IdString != idString)
					{
						the_Id_is_already_existing = true;
					}
					else
					{
						the_Id_is_already_existing = false;
					}
				}
			}
			else
			{
				the_Id_is_already_existing = false;
			}

			if (the_Id_is_already_existing)
			{
				DataRow alreadyExistingDataRow_Language
				= dataTable_Language.Rows
				.Find(new object[] { id, this.Current__Language.Code });

				string errorMessage =
					"The '" + tableName + " Id' (" +
					idString +
					") is not valid because it is already associated to the existing " + tableName + " : '" +
					alreadyExistingDataRow.Field<string>("UniqueKeyString") +
					"' that means : '" +
					alreadyExistingDataRow_Language.Field<string>("Meaning") +
					"'.";

				textBox_WEM__Id.SetError(errorMessage, "" + tableName + " Id already existing");

				id = -1;
			}
			else
			{
				textBox_WEM__Id.ClearError();
			}
		}

		/// UniqueKeyString
		internal void Word_Pattern__UniqueKeyString__TextChanged(bool t_for_W__f_for_P,	TextBox_WEM textBox_WEM__UniqueKeyString)
		{
			if (textBox_WEM__UniqueKeyString == null)
			{
				return;
			}

			string		tableName			= (t_for_W__f_for_P ? "Word" : "Pattern");
			DataTable	dataTable			= this.DataSet.Tables[tableName];
			DataTable	dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			string uniqueKeyString = textBox_WEM__UniqueKeyString.Text();

			/// empty?
			if (string.IsNullOrEmpty(uniqueKeyString))
			{
				textBox_WEM__UniqueKeyString.SetError
				(
					"The value of the '" + tableName + "' String' cannot be empty.", 
					"'" + tableName + " String' required"
				);

				return;
			}

			/// made of Letters (Word) or of LetterOrSymbols (Pattern)?
			string invalidLetter_Symbol = this.check__UniqueKeyString(uniqueKeyString, t_for_W__f_for_P);
			if (invalidLetter_Symbol != null)
			{
				textBox_WEM__UniqueKeyString.SetError
				(
					"The '" + tableName + "' String' contains an invalid character (= '" + invalidLetter_Symbol + "').",
					"Invalid character"
				);

				return;
			}

			/// unique?
			string current__UniqueKeyString = textBox_WEM__UniqueKeyString.Reference; 

			bool the_UniqueKeyString_is_already_existing;

			DataRow[] alreadyExistings = dataTable.Select("UniqueKeyString = '" + uniqueKeyString + "'");
			
			DataRow alreadyExisting;

			if (alreadyExistings.Length == 1)
			{
				alreadyExisting = alreadyExistings[0];

				if (current__UniqueKeyString == null)
				{
					/// Create
					the_UniqueKeyString_is_already_existing = true;
				}
				else
				{
					
					if (current__UniqueKeyString != uniqueKeyString)
					{
						the_UniqueKeyString_is_already_existing = true;
					}
					else
					{
						the_UniqueKeyString_is_already_existing = false;
					}
				}
			}
			else
			{
				alreadyExisting = null;

				the_UniqueKeyString_is_already_existing = false;
			}

			if (the_UniqueKeyString_is_already_existing)
			{
				DataRow alreadyExisting_Language
				= dataTable_Language.Rows
				.Find( new object[] { (int)alreadyExisting["Id"], this.Current__Language.Code } );

				string errorMessage =
					"The '" + tableName + " String' (" +
					uniqueKeyString +
					") is not valid because it is already associated to the existing " + tableName + "(Id = " +
					((int)alreadyExisting["Id"]).ToString() +
					") that means : '" +
					(string)alreadyExisting_Language["Meaning"] +
					"'.";

				textBox_WEM__UniqueKeyString.SetError(errorMessage,	"'" + tableName + " String' already existing");

				return;
			}

			textBox_WEM__UniqueKeyString.ClearError();
		}

		/// return null if no char error, elsewhere the first invalid char.
		private string check__UniqueKeyString(string uniqueKeyString, bool t_for_W__f_for_P)
		{
			string tableName = (t_for_W__f_for_P ? "Letter" : "LetterOrSymbol");
			DataTable dataTable = this.DataSet.Tables[tableName];

			for (int i = 0; i < uniqueKeyString.Length; i++)
			{
				char firstChar = uniqueKeyString[i];

				if (i < uniqueKeyString.Length - 1)
				{
					char secondChar = uniqueKeyString[i + 1];

					string doubleCharLetterOrSymbol = new string(new char[] { firstChar, secondChar });

					DataRow doubleCharLetterRow
						= dataTable.Rows.Find(doubleCharLetterOrSymbol);

					if (doubleCharLetterRow != null)
					{
						i++;

						continue;
					}
				}

				string monoCharLetter = new string(new char[] { firstChar });

				DataRow monoCharLetterRow
					= dataTable.Rows.Find(monoCharLetter);

				if (monoCharLetterRow == null)
				{
					return monoCharLetter;
				}
			}

			return null;
		}

		/// Meaning
		internal void Word_Pattern__Meaning__TextChanged(bool t_for_W__f_for_P, TextBox_WEM textBox_WEM__Meaning)
		{
			if (textBox_WEM__Meaning == null)
			{ 
				return;
			}

			string		tableName			= (t_for_W__f_for_P ? "Word" : "Pattern");
			DataTable	dataTable			= this.DataSet.Tables[tableName];
			DataTable	dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			string meaning = textBox_WEM__Meaning.Text();

			/// empty?
			if (string.IsNullOrEmpty(meaning))
			{
				textBox_WEM__Meaning.SetError
				(
					"The value of the '" + tableName + " Meaning' cannot be empty.",
					"'" + tableName + " Meaning' required"
				);
				return;
			}

			string current__Meaning = textBox_WEM__Meaning.Reference;

			if (meaning.Length > dataTable_Language.Columns["Meaning"].MaxLength)
			{ 
				textBox_WEM__Meaning.SetError
				(
					"The value of the '" + tableName + " Meaning' is too long.",
					"Max. Length is = '" + dataTable_Language.Columns["Meaning"].MaxLength.ToString() + "'"
				);
				return;
			}


			bool the_Meaning_is_already_existing;

			
			string filteringExpression 
				= "LanguageCode = '" + this.Current__Language.Code + "' AND Meaning = '" + meaning.Replace("'", "''") + "'";  

			DataRow[] alreadyExistings_Language = dataTable_Language.Select(filteringExpression);
			
			DataRow alreadyExisting_Language;

			if (alreadyExistings_Language.Length == 1)
			{
				alreadyExisting_Language = alreadyExistings_Language[0];

				if (current__Meaning == null)
				{
					the_Meaning_is_already_existing = true;
				}
				else
				{
					if (current__Meaning != meaning)
					{
						the_Meaning_is_already_existing = true;
					}
					else
					{
						the_Meaning_is_already_existing = false;
					}
				}
			}
			else
			{
				alreadyExisting_Language = null;

				the_Meaning_is_already_existing = false;
			}

			if (the_Meaning_is_already_existing)
			{
				DataRow alreadyExisting = alreadyExisting_Language.GetParentRow(tableName + "_Language__" + tableName);

				string errorMessage =
					"The '" + tableName + " Meaning' (" +
					meaning +
					") is not valid because it is already associated to the existing " + tableName + " : '" +
					(string)alreadyExisting["UniqueKeyString"] +
					"' [Id = " + ((int)alreadyExisting["Id"]).ToString() + "].";

				textBox_WEM__Meaning.SetError
				(
					errorMessage,
					"'" + tableName + " Meaning' already existing"
				);
				return;
			}

			textBox_WEM__Meaning.ClearError();
		}

		/// create a word without extension
		internal void Create__Word_Pattern
		(
			bool	t_for_W__f_for_P,
			int		id,
			string	uniqueKeyString,
			string	meaning,
			BabebiDataSet.WordTypeRow wordType,
		out	DataRow	current__WordOrPattern,
		out	DataRow	current__DataRow,					
		out	DataRow	current__DataRow_Language,			
			string modeCode
		)
		{ 
			string		tableName			= (t_for_W__f_for_P ? "Word" : "Pattern");
			string		subscriberCode		= (t_for_W__f_for_P ? MainForm.SubscriberCode_Word : MainForm.SubscriberCode_Pattern);
			DataTable	dataTable			= this.DataSet.Tables[tableName];
			DataTable	dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			#region		creating of single rows

			/// on reste en typé.
			current__WordOrPattern
				= this.DataSet.WordOrPattern
				.AddWordOrPatternRow
				(
					subscriberCode,
					id
				);

			List<object> columnValues = new List<object>();
			#region		build the values of the columns

			columnValues.Add(id);
			columnValues.Add(uniqueKeyString);
			if (t_for_W__f_for_P)
			{
				columnValues.Add(wordType.Id);
			}
			columnValues.Add(modeCode);
			if (t_for_W__f_for_P)
			{
				columnValues.Add(false);
			}
			columnValues.Add(subscriberCode);

			#endregion	build the values of the columns

			current__DataRow = dataTable.Rows.Add(columnValues.ToArray());
			
			#endregion	creating of single rows
			#region		the Word_Language links

			current__DataRow_Language = null;	/// pour que le 'out' marche...

			foreach (BabebiDataSet.LanguageRow language in this.DataSet.Language)
			{
				columnValues.Clear();
				#region		build the values of the columns

				columnValues.Add(id);
				columnValues.Add(language.Code);
				if (t_for_W__f_for_P)
				{
					columnValues.Add(wordType.Id);
				}
				columnValues.Add((language == this.Current__Language ? "" : "**" + this.Current__Language.Code + "**") + meaning);

				#endregion	build the values of the columns

				DataRow dataRow_Language = dataTable_Language.Rows.Add(columnValues.ToArray());

				if (language == this.Current__Language)
				{
					current__DataRow_Language = dataRow_Language;
				}
			}

			#endregion	the Word_Language links
		}

		/// Update a word without extension
		internal void Update__Word_Pattern
		(
			bool	t_for_W__f_for_P,
			int		id,
			string	uniqueKeyString,
			string	meaning,
			BabebiDataSet.WordTypeRow		wordType,
			BabebiDataSet.WordOrPatternRow	current__WordOrPattern,	/// indispensable pour pouvoir updater l'Id...					
			DataRow							current__DataRow,					
			DataRow							current__DataRow_Language,
		out BabebiDataSet.LanguageWordRow	current__LanguageWord
		)
		{
			string		tableName			= (t_for_W__f_for_P ? "Word" : "Pattern");
			string		subscriberCode		= (t_for_W__f_for_P ? MainForm.SubscriberCode_Word : MainForm.SubscriberCode_Pattern);
			DataTable	dataTable			= this.DataSet.Tables[tableName];
			DataTable	dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];



			/// UniqueKeyString
			if (current__DataRow.Field<string>("UniqueKeyString") != uniqueKeyString)
			{ 
				WordOrPattern.SetUniqueKeyString(t_for_W__f_for_P, current__DataRow, uniqueKeyString);
			}

			/// WordTypeId
			if (t_for_W__f_for_P)
			{
				if (current__DataRow.Field<short>("WordTypeId") != wordType.Id)
				{
					/// si le Word a un WordDerivating, alors on ne peut pas changer le WordType car
					/// WordDerivating a une state vers DerivatingWordType qui est contraint par le
					/// WordType cascadé.
					 
					BabebiDataSet.WordRow word = (BabebiDataSet.WordRow)current__DataRow;

					if (word.HasDerivating)
					{
						MessageBox.Show
						(
							"You are trying to update the 'Word Type' of the Word (" + word.UniqueKeyString + ") but " +
							"this Word has a 'Word (Derivating)' extension pointing to a 'Derivating Word Type' that " +
							"is contrained by the existing/prior 'Word Type', and so, it would become faulty due to this " +
							"'Word Type' switching attempt.\n\n" +
							"You have to remove first : \n\n" +
							"1) all the child 'Words (Derivated)' and \n" +
							"2) the prior 'Word (Derivating)' extension.\n\n" +
							"In between this 'Word Type' updating attemps aborts : the input value will be ignored and " +
							"the prior value will remain.",
							"No 'Word Type' updating",
							MessageBoxButtons.OK,
							MessageBoxIcon.Information
						);
					}
					else
					{
						current__DataRow["WordTypeId"] = wordType.Id;
					}
				}
			}

			/// Id : on le met en dernier car sinon on constate que cela ne marche pas :
			/// le changement d'Id fait que le row enfant (ex = WDed) devient introuvable 
			/// (le cascading ne se fait pas assez précocement ?) et le recalcul de la 
			/// propagation de la UKS plante (ex = WDed est trouvé à null).
			if (current__WordOrPattern.SubscriberId != id)
			{ 
				current__WordOrPattern.SubscriberId = id;	/// cascading.
			}
		
			current__LanguageWord = null;

			DataRow[] dataRows_Language = current__DataRow.GetChildRows(tableName + "_Language__" + tableName).ToArray();

			foreach (DataRow dataRow_Language in dataRows_Language)
			{
				string dataRow_Language__LanguageCode	= dataRow_Language.Field<string>("LanguageCode");
				string dataRow_Language__Meaning		= dataRow_Language.Field<string>("Meaning");

				if (dataRow_Language__LanguageCode == this.Current__Language.Code)
				{
					/// alors word_Language == current__Word_Language

					if (dataRow_Language__Meaning != meaning)
					{ 
						dataRow_Language["Meaning"] = meaning;

						if (t_for_W__f_for_P)
						{
							BabebiDataSet.Word_LanguageRow current__Word_Language = (BabebiDataSet.Word_LanguageRow)current__DataRow_Language;

							MeaningParser meaningParser = new MeaningParser(this, meaning);

							bool successful = meaningParser.Parse();

							if (!successful)
							{
								MessageBox.Show(meaningParser.ErrorMessage, "While parsing Meaning", MessageBoxButtons.OK, MessageBoxIcon.Error);
							}
							else
							{
								foreach 
								(
									BabebiDataSet.Word_LanguageWordRow word_LanguageWord 
									in 
									current__Word_Language.GetWord_LanguageWordRows().ToArray()
								)
								{
									if (!meaningParser.LanguageWordStrings.Contains(word_LanguageWord.LanguageWordString))
									{
										/// ce LW doit disparaitre s'il est "captif".
										
										if (word_LanguageWord.LanguageWordRowParent.GetWord_LanguageWordRows().Length == 1)
										{
											/// captif => on supprime le LW (et le W_LW par cascade).
											
											this.DataSet.LanguageWord.RemoveLanguageWordRow(word_LanguageWord.LanguageWordRowParent);
										}
										else
										{
											/// no captif => on supprime le W_LW seulement.
											
											this.DataSet.Word_LanguageWord.RemoveWord_LanguageWordRow(word_LanguageWord);
										}
									}
								}

								foreach (string languageWordString in meaningParser.LanguageWordStrings)
								{ 
									BabebiDataSet.LanguageWordRow languageWord
										= this.DataSet.LanguageWord
										.FindByLanguageCodeString
										(
											this.Current__Language.Code, 
											languageWordString
										);

									if (languageWord == null)
									{
										languageWord
										= this.DataSet.LanguageWord
										.AddLanguageWordRow
										(
											this.Current__Language, 
											languageWordString
										);
									}

									if (current__LanguageWord == null)
									{
										current__LanguageWord = languageWord;
									}

									BabebiDataSet.Word_LanguageWordRow word_LanguageWord
										= this.DataSet.Word_LanguageWord
										.FindByWordIdLanguageCodeLanguageWordString
										(
											id,
											this.Current__Language.Code,
											languageWordString
										);

									if (word_LanguageWord == null)
									{
										word_LanguageWord
										= this.DataSet.Word_LanguageWord
										.AddWord_LanguageWordRow
										(
											id,
											this.Current__Language.Code, 
											languageWordString
										);
									}

								}
							}
						}
					}
				}
				else	/// (dataRow_Language__LanguageCode != this.Current__Language.Code)
				{
					if ( dataRow_Language__Meaning.StartsWith("**") )
					{
						dataRow_Language["Meaning"] = "**" + this.Current__Language.Code + "**" + meaning;
					}
					else
					{
						/// on n'y touche pas car ce n'est plus une valeur 'automatique' mais bien une valeur saisie.
					}
				}
			}
		}

		internal void Ctor__CreateUpdate__Word_Pattern
		(
			bool			t_for_W__f_for_P,
			Form			form,
			Button			button__CreateUpdate,
			Button			button__Clone,
			string			modeName,
			Label			label__Id, 
			Label			label__UniqueKeyString,
			Label			label__Meaning,
			Label			label__WordType,
			TextBox			textBox__Id, 
			TextBox			textBox__UniqueKeyString,
			TextBox			textBox__Meaning,
			ComboBox		comboBox__WordType,
			bool			isUniqueKeyStringComputed,
		out	TextBox_WEM		textBox_WEM__Id, 
		out	TextBox_WEM		textBox_WEM__UniqueKeyString,
		out	TextBox_WEM		textBox_WEM__Meaning,
		out	ComboBox_WEM	comboBox_WEM__WordType,
			bool			trueForCreate__falseForUpdate,
		ref int				id,
		ref BabebiDataSet.WordType_LanguageRow selected__WordType_Language,
			DataRow			current__DataRow,					
			DataRow			current__DataRow_Language
		)
		{
			string		tableName			= (t_for_W__f_for_P ? "Word" : "Pattern");
			string		subscriberCode		= (t_for_W__f_for_P ? MainForm.SubscriberCode_Word : MainForm.SubscriberCode_Pattern);
			DataTable	dataTable			= this.DataSet.Tables[tableName];
			DataTable	dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			#region		WEM

			textBox_WEM__Id				
				= new TextBox_WEM
				(
					label__Id, 
					textBox__Id, 
					"The '" + tableName + " Id' field is empty.", 
					"Missing '" + tableName + " Id'",
					(trueForCreate__falseForUpdate ? null :	current__DataRow.Field<int>("Id").ToString())
				);

			textBox_WEM__UniqueKeyString	
				= new TextBox_WEM
				(
					label__UniqueKeyString, 
					textBox__UniqueKeyString, 
					"The '" + tableName + " String' field is empty.", 
					"Missing '" + tableName + " String'",
					(trueForCreate__falseForUpdate ? null : current__DataRow.Field<string>("UniqueKeyString"))
				);

			textBox_WEM__Meaning	
				= new TextBox_WEM
				(
					label__Meaning, 
					textBox__Meaning, 
					"The '" + tableName + " Meaning' field is empty.", 
					"Missing '" + tableName + " Meaning'",
					(trueForCreate__falseForUpdate ? null : current__DataRow_Language.Field<string>("Meaning"))
				);

			if (t_for_W__f_for_P)
			{
				comboBox_WEM__WordType
					= new ComboBox_WEM
					(
						label__WordType,
						comboBox__WordType,
						"The '" + tableName + " Type' is not selected.",
						"Missing '" + tableName + " Type'",
						(trueForCreate__falseForUpdate ? null : current__DataRow_Language.GetParentRow(tableName + "_Language__WordType_Language").Field<string>("Name"))
					);
			}
			else
			{ 
				comboBox_WEM__WordType = null;
			}

			#endregion	WEM

			if (trueForCreate__falseForUpdate)
			{
				form.Text = "Create a new '" + tableName + "" + (modeName == MainForm.ModeName_NotDefined ? "" : " (" + modeName + ") ") + "' :";
				button__CreateUpdate.Text = "CREATE";

				if (button__Clone != null && current__DataRow == null)
				{
					button__Clone.Visible = false;	/// car on ne peut pas cloner si current__Word == null.
				}

				#region		Id

				id = this.Word_Pattern__Id__Next(t_for_W__f_for_P);

				textBox_WEM__Id.Set_with_no_error(id.ToString());

				#endregion	Id
				#region		WordType

				if (t_for_W__f_for_P)
				{
					List<WordTypeComboBoxItem> wordTypeComboBoxItems = WordTypeComboBoxItem.BuildWordTypeComboBoxItems(this.Current__Language);
					comboBox__WordType.Items.AddRange(wordTypeComboBoxItems.ToArray());

					selected__WordType_Language = null;
				}

				#endregion	WordType
			}
			else
			{
				form.Text = "Update an existing '" + tableName + "" + (modeName == MainForm.ModeName_NotDefined ? "" : " (" + modeName + ") ") + "' :";
				button__CreateUpdate.Text = "UPDATE";
				button__Clone.Visible = false;

				/// on doit mettre le field UniqueKeyString en RO si un (mode) a déjà été ajouté.
				if (current__DataRow.Field<string>("ModeCode") != ModeCode_NotDefined)
				{
					textBox__UniqueKeyString.ReadOnly = true;
				}

				/// Id
				id = current__DataRow.Field<int>("Id");
				textBox_WEM__Id.Set_with_no_error( id.ToString() );

				/// UniqueKeyString.
				if (!isUniqueKeyStringComputed)
				{
					textBox_WEM__UniqueKeyString.Set_with_no_error(current__DataRow.Field<string>("UniqueKeyString"));
				}

				/// Meaning
				textBox_WEM__Meaning.Set_with_no_error(current__DataRow_Language.Field<string>("Meaning"));

				/// WordType
				if (t_for_W__f_for_P)
				{
					#region		comboBox WordType
					
					BabebiDataSet.Word_LanguageRow current__Word_Language = (BabebiDataSet.Word_LanguageRow)current__DataRow_Language;

					/// pour le retour en 'ref'
					selected__WordType_Language = current__Word_Language.WordType_LanguageRowParent;

					WordTypeComboBoxItem focusedWordTypeComboBoxItem;
					List<WordTypeComboBoxItem> wordTypeComboBoxItems
						= WordTypeComboBoxItem
						.BuildWordTypeComboBoxItems
						(
							this.Current__Language,
							current__Word_Language.WordType_LanguageRowParent,
						out focusedWordTypeComboBoxItem
						);

					comboBox__WordType.Items.AddRange(wordTypeComboBoxItems.ToArray());

					if (focusedWordTypeComboBoxItem != null)
					{
						comboBox__WordType.SelectedItem = focusedWordTypeComboBoxItem;
					}

					comboBox_WEM__WordType.ClearError();

					#endregion	comboBox WordType				
				}
			}
		}

		internal void Clone__Word_Pattern
		(
			bool		t_for_W__f_for_P,
			TextBox		textBox__UniqueKeyString,
			TextBox		textBox__Meaning,
			ComboBox	comboBox__WordType,
			bool		isUniqueKeyStringComputed,
			DataRow		current__DataRow,		
			DataRow		current__DataRow_Language
		)
		{
			/// UniqueKeyString
			if (!isUniqueKeyStringComputed)
			{
				textBox__UniqueKeyString.Text = current__DataRow.Field<string>("UniqueKeyString") + "babebi";
			}

			/// Meaning
			textBox__Meaning	.Text = current__DataRow_Language.Field<string>("Meaning")  + "undeuxtrois";

			/// WordType
			if (t_for_W__f_for_P)
			{
				BabebiDataSet.Word_LanguageRow	current__Word_Language = (BabebiDataSet.Word_LanguageRow)current__DataRow_Language;

				WordTypeComboBoxItem focusedWordTypeComboBoxItem
					= new WordTypeComboBoxItem(current__Word_Language.WordType_LanguageRowParent);
				comboBox__WordType.SelectedItem = focusedWordTypeComboBoxItem;
			}
		}

		#endregion	functions
		#region		search methods

		/// <summary>
		/// return true if only 1.
		/// return false if N with 1 matching.
		/// return null if N with no matching.
		/// </summary>
		internal bool? textBox__Search__UniqueKeyString__TextChanged
		(
			bool		t_for_W__f_for_P			,
			TextBox		textBox__UniqueKeyString	,
			TextBox		textBox__Meaning			,
			DataTable	guiTable					,
			string		hide_this_UniqueKeyString	,
		out DataRow		selected__DataRow			, 
		out DataRow		selected__DataRow_Language	
		)
		{
			string tableName = (t_for_W__f_for_P ? "Word" : "Pattern");
			DataTable dataTable				= this.DataSet.Tables[tableName];
			DataTable dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			/// returned values if no selection => return false.
			selected__DataRow			= null;
			selected__DataRow_Language	= null;

			string uniqueKeyString = textBox__UniqueKeyString.Text;

			if (string.IsNullOrEmpty(uniqueKeyString))
			{
				return null;
			}

			textBox__Meaning.Text = null;

			guiTable.Clear();

			if (uniqueKeyString.Length < 2)
			{ 
				return null;
			}

			string filter =	"UniqueKeyString LIKE '*" + uniqueKeyString + "*'";

			if (hide_this_UniqueKeyString != null)
			{
				filter += " AND NOT(UniqueKeyString = '" + hide_this_UniqueKeyString + "')";
			}
					
			DataRow[] selectedDataRows = dataTable.Select(filter);

			if (selectedDataRows.Length == 1)
			{
				selected__DataRow = selectedDataRows[0];

				selected__DataRow_Language
					= dataTable_Language.Rows
					.Find( new object[] { selected__DataRow.Field<int>("Id"), this.Current__Language.Code }	);

				this.textBox__Pattern__UniqueKeyString	.Text	= null;

				return true;
			}
			else
			{
				DataRow matchingGuiDataRow = null;

				foreach (DataRow selectedDataRow in selectedDataRows)
				{
					DataRow selectedDataRow_Language
						= dataTable_Language.Rows
						.Find(new object[] { selectedDataRow.Field<int>("Id"), this.Current__Language.Code });

					DataRow guiDataRow 
						= guiTable.Rows
						.Add
						(
							selectedDataRow			.Field<int		>("Id"),
							selectedDataRow			.Field<string	>("UniqueKeyString"),
							selectedDataRow_Language.Field<string	>("Meaning")
						);

					if (matchingGuiDataRow == null && selectedDataRow.Field<string>("UniqueKeyString") == uniqueKeyString)
					{
						matchingGuiDataRow = guiDataRow;
					}
				}

				if (matchingGuiDataRow != null)
				{
					int	selectedId = matchingGuiDataRow.Field<int>("Id");

					selected__DataRow
						= dataTable.Rows
						.Find(selectedId);
			
					selected__DataRow_Language
						= dataTable_Language.Rows
						.Find( new object[] { selectedId, this.Current__Language.Code } );

					return false;
				}
				else
				{
					return null; 
				}
			}
		}

		/// <summary>
		/// return true if only 1.
		/// return false if N with 1 matching.
		/// return null if N with no matching.
		/// </summary>
		internal bool? textBox__Search__Meaning__TextChanged
		(
			bool		t_for_W__f_for_P,
			TextBox		textBox__UniqueKeyString,
			TextBox		textBox__Meaning,
			DataTable	guiTable,
		out DataRow		selected__DataRow, 
		out DataRow		selected__DataRow_Language,
			bool		even1CharMeaning = false
		)
		{
			string tableName = (t_for_W__f_for_P ? "Word" : "Pattern");
			DataTable dataTable				= this.DataSet.Tables[tableName];
			DataTable dataTable_Language	= this.DataSet.Tables[tableName + "_Language"];

			/// returned values if no selection => return false.
			selected__DataRow			= null;
			selected__DataRow_Language	= null;

			string meaning = textBox__Meaning.Text;

			if (string.IsNullOrEmpty(meaning))
			{
				return null;
			}

			textBox__UniqueKeyString.Text = null;

			guiTable.Clear();

			if (meaning.Length == 0)
			{
				return null;
			}

			DataRow[] selectedDataRow_Languages
				= dataTable_Language
				.Select
				(
					"LanguageCode = '" + this.Current__Language.Code + "' AND Meaning LIKE '*" + meaning + "*'"
				);

			if (selectedDataRow_Languages.Length == 1)
			{
				selected__DataRow_Language	= selectedDataRow_Languages[0];

				selected__DataRow			= selected__DataRow_Language.GetParentRow(tableName + "_Language__" + tableName);

			//	textBox__Meaning.Text = null;

				return true;
			}
			else
			{
				DataRow matchingGuiDataRow = null;

				foreach (DataRow selectedDataRow_Language_ in selectedDataRow_Languages)
				{
					DataRow selectedDataRow_ = selectedDataRow_Language_.GetParentRow(tableName + "_Language__" + tableName);

					DataRow guiDataRow
						= guiTable
						.Rows
						.Add
						(
							selectedDataRow_			.Field<int		>("Id"),
							selectedDataRow_			.Field<string	>("UniqueKeyString"),
							selectedDataRow_Language_	.Field<string	>("Meaning")
						);

					if (matchingGuiDataRow == null && selectedDataRow_Language_.Field<string>("Meaning") == meaning)
					{
						matchingGuiDataRow = guiDataRow;
					}
				}

				if (matchingGuiDataRow == null && t_for_W__f_for_P)
				{
					BabebiDataSet.LanguageWordRow languageWord
						= this.DataSet.LanguageWord
						.FindByLanguageCodeString
						(
							this.Current__Language.Code, 
							meaning
						);

					if (languageWord != null)
					{
						List<BabebiDataSet.Word_LanguageRow> word_LanguageList = new List<BabebiDataSet.Word_LanguageRow>();

						foreach (BabebiDataSet.Word_LanguageWordRow word_LanguageWord in languageWord.GetWord_LanguageWordRows())
						{
							word_LanguageList.Add(word_LanguageWord.Word_LanguageRowParent);
						}

						foreach (BabebiDataSet.Word_LanguageRow word_LanguageRow in selectedDataRow_Languages)
						{
							if (word_LanguageList.Contains(word_LanguageRow))
							{
								matchingGuiDataRow = guiTable.Rows.Find(word_LanguageRow.WordId);
								break;
							}
						}
					}
				}

				if (matchingGuiDataRow != null)
				{
					int selectedId = matchingGuiDataRow.Field<int>("Id");

					selected__DataRow
						= dataTable.Rows
						.Find(selectedId);
			
					selected__DataRow_Language
						= dataTable_Language.Rows
						.Find( new object[] { selectedId, this.Current__Language.Code });

					return false;
				}
				else
				{
					return null;
				}
			}
		}

		#endregion	search methods

	}
}