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 Form__WordFromPattern__CreateUpdate : Form
	{
		private MainForm		mainForm;
		private BabebiDataSet	dataSet;

		private bool trueForCreate__falseForUpdate
		{
			get
			{
				if (this.current__WordFromPattern == null)
				{
					return true;
				}
				else
				{ 
					if (this.current__WordFromPattern.Id != this.current__Word.Id)
					{
						return true;
					}
					else
					{ 
						return false;
					}
				}
			}
		}

		#region		short-cuts

		private BabebiDataSet.FromPatternDataTable			table__FromPattern			{ get { return this.dataSet.FromPattern; } }
		private BabebiDataSet.FromPatternLetterDataTable	table__FromPatternLetter	{ get { return this.dataSet.FromPatternLetter; } }

		private BabebiDataSet.WordDataTable					table__Word					{ get { return this.mainForm.DataSet.Word				; } }
		private BabebiDataSet.Word_LanguageDataTable		table__Word_Language		{ get { return this.mainForm.DataSet.Word_Language		; } }
		private BabebiDataSet.WordFromPatternDataTable		table__WordFromPattern		{ get { return this.mainForm.DataSet.WordFromPattern	; } }

		private BabebiDataSet.LetterDataTable				table__Letter				{ get { return this.dataSet.Letter; } }
		private BabebiDataSet.SymbolDataTable				table__Symbol				{ get { return this.dataSet.Symbol; } }
		private BabebiDataSet.LetterOrSymbolDataTable		table__LetterOrSymbol		{ get { return this.dataSet.LetterOrSymbol; } }

		private BabebiDataSet.PatternDataTable				table__Pattern				{ get { return this.mainForm.DataSet.Pattern			; } }
		private BabebiDataSet.Pattern_LanguageDataTable		table__Pattern_Language		{ get { return this.mainForm.DataSet.Pattern_Language	; } }

		#endregion	short-cuts
		#region		the 2 gui tables

		private DataSet			guiDataSet;

		#region		gui table : Pattern

		private DataTable		guiTable__Pattern;

		private DataColumn		guiColumn__Pattern__Id;
		private DataColumn		guiColumn__Pattern__String;
		private DataColumn		guiColumn__Pattern__Meaning;

		private BindingSource	bindingSource__Pattern;

		#endregion	gui table : Pattern
		#region		gui table : FromPatternLetter

		private DataTable guiTable__FromPatternLetter;

		private DataColumn guiColumn__FromPatternLetter__Rank;
		private DataColumn guiColumn__FromPatternLetter__LetterTypeCode;
		private DataColumn guiColumn__FromPatternLetter__LetterString;

		private BindingSource bindingSource__FromPatternLetter;

		#endregion	gui table : FromPatternLetter

		#endregion	the 2 gui tables
		#region		current__#s

		private BabebiDataSet.WordOrPatternRow		current__WordOrPattern
		{
			get
			{
				return this.mainForm.Current__WordOrPattern__of__Word;
			}
		}
		private BabebiDataSet.WordRow				current__Word
		{
			get
			{
				return this.mainForm.Current__Word;
			}
		}
		private BabebiDataSet.Word_LanguageRow		current__Word_Language
		{
			get
			{
				return this.mainForm.Current__Word_Language;
			}
		}
		private BabebiDataSet.WordFromPatternRow	current__WordFromPattern
		{
			get
			{
				return this.mainForm.Current__WordFromPattern;
			}
			set
			{
				this.mainForm.Current__WordFromPattern = value;
			}
		}
		private BabebiDataSet.FromPatternRow		current__FromPattern
		{
			get
			{
				return this.mainForm.Current__FromPattern__of__WordFromPattern;
			}
			set
			{
				this.mainForm.Current__FromPattern__of__WordFromPattern = value;
			}
		}

		private BabebiDataSet.PatternRow			current__Pattern
		{
			get
			{
				return this.mainForm.Current__Pattern__of__WordFromPattern__Parent;
			}
			set
			{
				this.mainForm.Current__Pattern__of__WordFromPattern__Parent = value;
			}
		}
		private BabebiDataSet.Pattern_LanguageRow	current__Pattern_Language
		{
			get
			{
				return this.mainForm.Current__Pattern_Language__of__WordFromPattern__Parent;
			}
			set
			{
				this.mainForm.Current__Pattern_Language__of__WordFromPattern__Parent = value;
			}
		}

		#endregion	current__#s
		#region		variables

		#region		about the (base) Word		

		private List<BabebiDataSet.LetterRow>	letters__of__Word__UniqueKeyString;	/// l'épellation de la UniqueKyString du (parent) Pattern.
		private SortedDictionary<short, Letter>	ranks__letters;

		#endregion	about the (base) Word		
		#region		about the selected Pattern		

		private BabebiDataSet.PatternRow			selected__Pattern			= null;
		private BabebiDataSet.Pattern_LanguageRow	selected__Pattern_Language	= null;

		private List<BabebiDataSet.LetterOrSymbolRow>		letterOrSymbols__of__Pattern__UniqueKeyString;
		private Dictionary<short, BabebiDataSet.SymbolRow>	ranks__symbols;									/// n'avait pas besoin d'être 'Sorted' car construit dans le bon ordre. 
		private List<string>								pattern_Remaining_SubStrings;					/// les morceaux de strings autour des Symbols.

		#endregion	about the selected Pattern		

		private short selected__GuiHorizontalShift;

		#endregion	variables
		#region		error management

		private NoControl_WEM	noControl_WEM__PARENT_Pattern	;
		private TextBox_WEM		textBox_WEM__UniqueKeyString	;
		private ComboBox_WEM	comboBox_WEM__GuiHorizontalShift;

		#endregion	error management

		#region		ctors

		public Form__WordFromPattern__CreateUpdate(MainForm mainForm) : this()
		{
			this.mainForm	= mainForm;
			this.dataSet	= this.mainForm.DataSet;

			#region		the 2 gui tables

			this.guiDataSet = new DataSet("GuiDataSet");

			#region		guiTable__Pattern

			this.guiTable__Pattern = this.guiDataSet.Tables.Add("Pattern");

			this.guiColumn__Pattern__Id		= this.guiTable__Pattern.Columns.Add("Id", typeof(int));
			this.guiColumn__Pattern__String	= this.guiTable__Pattern.Columns.Add("String", typeof(string));
			this.guiColumn__Pattern__Meaning = this.guiTable__Pattern.Columns.Add("Meaning", typeof(string));

			this.guiTable__Pattern.PrimaryKey = new DataColumn[] { this.guiColumn__Pattern__Id };

			this.bindingSource__Pattern = new BindingSource(this.guiDataSet, this.guiTable__Pattern.TableName);

			this.dataGridView__Pattern.DataSource = this.bindingSource__Pattern;

			this.bindingSource__Pattern.CurrentChanged += bindingSource__Pattern__CurrentChanged;

			#endregion	guiTable__Pattern
			#region		guiTable__FromPatternLetter

			this.guiTable__FromPatternLetter = this.guiDataSet.Tables.Add("FromPatternLetter");

			this.guiColumn__FromPatternLetter__Rank				= this.guiTable__FromPatternLetter.Columns.Add("Rank", typeof(short));
			this.guiColumn__FromPatternLetter__LetterTypeCode	= this.guiTable__FromPatternLetter.Columns.Add("LetterTypeCode", typeof(string));
			this.guiColumn__FromPatternLetter__LetterString		= this.guiTable__FromPatternLetter.Columns.Add("LetterString", typeof(string));

			this.guiTable__FromPatternLetter.PrimaryKey = new DataColumn[] { this.guiColumn__FromPatternLetter__Rank };

			this.bindingSource__FromPatternLetter = new BindingSource(this.guiDataSet, this.guiTable__FromPatternLetter.TableName);

			this.dataGridView__FromPatternLetter.DataSource = this.bindingSource__FromPatternLetter;

			this.bindingSource__FromPatternLetter.CurrentChanged += bindingSource__FromPatternLetter__CurrentChanged;

			#endregion	guiTable__FromPatternLetter

			#endregion	the 2 gui tables
			#region		error management

			this.noControl_WEM__PARENT_Pattern 
				= new NoControl_WEM
				(
					"The parent Pattern has not been selected.", 
					"Missing parent Pattern"
				);

			this.comboBox_WEM__GuiHorizontalShift 
				= new ComboBox_WEM
				(
					this.label__GuiHorizontalShift,
					this.comboBox__GuiHorizontalShift,
					(this.trueForCreate__falseForUpdate ? null : this.current__WordFromPattern.FromPatternRowParent.GuiHorizontalShift.ToString())
				);

			this.textBox_WEM__UniqueKeyString = new TextBox_WEM
			(
				this.label__ComputedString,
				this.textBox__ComputedString,
				"The Unique Key String has never been computed.", 
				"Missing Computed String",
				this.current__Word.UniqueKeyString	/// oui : ici, même en mode Create, le UKS existe déjà.
			);


			#endregion	error management
			#region		analyse the 'Unique Key String' of the Word => letters__of__Word__UniqueKeyString.

			this.letters__of__Word__UniqueKeyString = new List<BabebiDataSet.LetterRow>();

			string errorCharString 
				= this.mainForm.Split_a_string_into_Letters
				(
					this.current__Word.UniqueKeyString, 
					this.letters__of__Word__UniqueKeyString
				);

			if (errorCharString != null)
			{
				this.textBox_WEM__UniqueKeyString
					.SetError
					(
						"The 'Unique Key String' of the (base) Word contains the invalid character : '" + errorCharString + "'.\n" +
						"You have to come back to the (base) definition of this Word, and then, change its 'String'.", 
						"Invalid Character"
					);
				this.textBox_WEM__UniqueKeyString.ShowMessageBox();

				this.button__CreateUpdate.Visible = false;

				return;
			}

			#endregion	analyse the Unique Key String of the Word => letters__of__Word__UniqueKeyString.

			if (this.trueForCreate__falseForUpdate)
			{
				this.button__CreateUpdate.Text = "CREATE";
				this.Text = "Append a 'From Pattern' extension to the current Word :";

				this.ranks__letters = new SortedDictionary<short, Letter>();	/// pas d'existant.

				this.comboBox__GuiHorizontalShift.SelectedIndex = 0;
				this.selected__GuiHorizontalShift = 0;
			}
			else
			{
				this.button__CreateUpdate.Text = "UPDATE";
				this.Text = "Update the 'From Pattern' extension of the current Word :";

				#region		build ranks__letters from FromPatternLetter rows and display in DGV => event => ComputedString

				this.ranks__letters = FromPattern_.Build__ranks__letters__from__FromPatternLetters(this.current__FromPattern);

				#endregion	build ranks__letters from FromPatternLetter rows and display in DGV => event => ComputedString
				#region		about selected Pattern

				this.noControl_WEM__PARENT_Pattern.ClearError();

				this.selected__Pattern				= this.current__Pattern;
				this.selected__Pattern_Language		= this.current__Pattern_Language;

				this.after_Pattern_selecting(false);	/// false = 'ne construit pas les  ranks__letters qui ont été récupérés du DS'

				#endregion	about selected Pattern
				#region		about selected GuiHorizontalShift

				this.selected__GuiHorizontalShift				= this.current__FromPattern.GuiHorizontalShift;
				this.comboBox__GuiHorizontalShift.SelectedItem	= this.selected__GuiHorizontalShift.ToString();

				#endregion	about selected GuiHorizontalShift
			}
		}

		public Form__WordFromPattern__CreateUpdate()
		{
			InitializeComponent();
		}

		#endregion	ctors
		
		/// calcul des ranks__letters SPECIFIQUE à cette forme (Word.UKS constant + selection d'un Pattern)
		private void compute__ranks__letters__from__Pattern__UniqueKeyString()
		{
			#region		matching ?
			
			bool matching = true;   /// on suppose que l'on va pouvoir faire la méthode directe.

			SortedDictionary<short, Letter> candidate__ranks__letters = new SortedDictionary<short, Letter>();

			int letters__of__Word__UniqueKeyString__Count 
				= this.letters__of__Word__UniqueKeyString.Count;

			int letterOrSymbols__of__Pattern__UniqueKeyString__Count 
				= this.letterOrSymbols__of__Pattern__UniqueKeyString.Count;

			if (letterOrSymbols__of__Pattern__UniqueKeyString__Count != letters__of__Word__UniqueKeyString__Count)
			{
				matching = false;
			}
			else
			{
				/// pas vraiment possible d'optimiser en utilisant les pattern__remaining__subStrings 
				/// à cause des possibles voyelles-double-lettres en face de symboles.
				
				short rank = 0;
				for (short i = 0; i < letters__of__Word__UniqueKeyString__Count; i++)
				{
					#region		letter__Word

					BabebiDataSet.LetterRow letter__Word = this.letters__of__Word__UniqueKeyString[i];

					string typeCode__letter__Word = letter__Word.TypeCode;

					#endregion	letter__Word
					#region		letterOrSymbol__Pattern

					BabebiDataSet.LetterOrSymbolRow letterOrSymbol__Pattern = this.letterOrSymbols__of__Pattern__UniqueKeyString[i];

					BabebiDataSet.LetterRow letter__Pattern;
					BabebiDataSet.SymbolRow symbol__Pattern;

					string typeCode__letterOrSymbol__Pattern;
					if (letterOrSymbol__Pattern.ModeCode == MainForm.ModeCode_Letter)
					{
						letter__Pattern = this.table__Letter.FindByString(letterOrSymbol__Pattern.String);
						symbol__Pattern = null;

						typeCode__letterOrSymbol__Pattern = letter__Pattern.TypeCode;
					}
					else if (letterOrSymbol__Pattern.ModeCode == MainForm.ModeCode_Symbol)
					{
						letter__Pattern = null;
						symbol__Pattern = this.table__Symbol.FindByString(letterOrSymbol__Pattern.String);

						typeCode__letterOrSymbol__Pattern = symbol__Pattern.TypeCode;

						/// on compte donc bien le nombre d'occurences des symboles dans la string parent pattern.
						/// MAIS on aurait pu aussi le faire juste avant le add() dans le dico ranks__letters plus bas
						/// puisque comme on travaille sur un Word (et pas un Pattern), tous les symboles vont être substituer
						/// par des Letters.
						rank++;	
					}
					else
					{
						throw new Exception();
					}

					#endregion	letterOrSymbol__Pattern

					if (typeCode__letterOrSymbol__Pattern != typeCode__letter__Word)
					{
						matching = false;   /// les deux caractères Word-Pattern doivent être du même type (voyelle ou consonne).
					}
					else
					{
						if (letter__Pattern != null)
						{
							if (letter__Word.String != letter__Pattern.String)
							{
								matching = false;   /// les 2 lettres doivent être identiques si côté Pattern on a une lettre.
							}
						}
						else
						{
							/// on a ici une substitution de symbole par une lettre : OK.
							candidate__ranks__letters.Add(rank, new Letter(letter__Word.TypeCode, letter__Word.String));
						}
					}
				}
			}

			/// si matching, alors on trappe le processus ici ; sinon on fait la méthode normale dessous.
			if (matching)
			{
				this.ranks__letters = candidate__ranks__letters;

				this.textBox__ComputedString.Text = this.current__Word.UniqueKeyString;		/// forcément puisque cela matche.

				this.textBox_WEM__UniqueKeyString.ClearError();

				return;
			}
			else
			{
				/// nettoyage de la tentative précédente.
				candidate__ranks__letters.Clear();
				candidate__ranks__letters = null;
			}

			#endregion	matching ?
			#region		adaption de ranks__letters par défaut.

			short max__of__both__ranks = -1;
			foreach (short rank in this.ranks__symbols.Keys)
			{
				if (rank >= max__of__both__ranks)
				{
					max__of__both__ranks = rank;
				}
			}
			foreach (short rank in this.ranks__letters.Keys)
			{
				if (rank >= max__of__both__ranks)
				{
					max__of__both__ranks = rank;
				}
			}
			
			/// tactique : ranks__symbols contient tous les ranks de 1 à 
			/// ranks__symbols.Count inclus, mais pas forcèment ranks__letters.
			/// ranks__symbols sert de modèle :
			/// - s'il y a des letters en trop, on les supprime.
			/// - s'il n'y en a pas assez, on en crée des par-défauts.
			/// - si des letters existent mais sont du mauvais type, alors on change le type et on met la première lettre par défaut.
			/// - si les letters existent + elles sont du bon type, alors on ne touche à rien.
			
			for (short rank = 1; rank <= max__of__both__ranks; rank++)
			{
				if (this.ranks__symbols.Keys.Contains(rank))
				{
					BabebiDataSet.SymbolRow symbol = this.ranks__symbols[rank];

					if (this.ranks__letters.Keys.Contains(rank))
					{
						Letter letter = this.ranks__letters[rank];

						if (letter.TypeCode == symbol.TypeCode)
						{
							/// on ne touche à rien pour conserver l'existant : le choix historique de la lettre pour ce rank.
						}
						else
						{
							/// le TypeCode de la fromPatternLetter n'est pas le bon => on adapte en venant pointer sur la premier letter du bon type (V ou C).

							if (symbol.TypeCode == MainForm.TypeCode_Vowel)
							{
								letter.TypeCode = this.mainForm.FirstVowel.TypeCode;
								letter.String	= this.mainForm.FirstVowel.String;
							}
							else if (symbol.TypeCode == MainForm.TypeCode_Consonant)
							{
								letter.TypeCode = this.mainForm.FirstConsonant.TypeCode;
								letter.String	= this.mainForm.FirstConsonant.String;
							}
							else
							{
								throw new Exception(symbol.TypeCode);
							}

							this.ranks__letters[rank] = letter;
						}
					}
					else
					{
						/// on rajoute la letter du bon type par défaut.
						
						Letter letter;
						if (symbol.TypeCode == MainForm.TypeCode_Vowel)
						{
							letter = new Letter(MainForm.TypeCode_Vowel, this.mainForm.FirstVowel.String);
						}
						else if (symbol.TypeCode == MainForm.TypeCode_Consonant)
						{
							letter = new Letter(MainForm.TypeCode_Consonant, this.mainForm.FirstConsonant.String);
						}
						else
						{
							throw new Exception();
						}

						this.ranks__letters.Add(rank, letter);
					}
				}
				else
				{ 
					/// il faut supprimer cette row surnuméraire car associée à aucun Symbol.
					this.ranks__letters.Remove(rank);
				}
			}

			#endregion	adaption de ranks__letters par défaut.
		}

		#region		GuiHorizontalShift

		private void comboBox__GuiHorizontalShift_SelectedIndexChanged(object sender, EventArgs e)
		{
			MainForm.FromPattern__comboBox__GuiHorizontalShift__SelectedIndexChanged
			(
				this.comboBox_WEM__GuiHorizontalShift,
			ref	this.selected__GuiHorizontalShift
			);
		}

		#endregion	GuiHorizontalShift
		#region		selecting of the (parent) Pattern

		private void after_Pattern_selecting(bool build__ranks__Letters)
		{
			this.noControl_WEM__PARENT_Pattern.ClearError();

			/// populate
			this.textBox__SelectedPattern__UniqueKeyString	.Text = this.selected__Pattern.UniqueKeyString;
			this.textBox__SelectedPattern__Meaning	.Text = this.selected__Pattern_Language.Meaning;
			this.textBox__SelectedPattern__Id		.Text = this.selected__Pattern.Id.ToString();

			/// analyse
			Pattern.Analyse__Pattern__UniqueKeyString
			(
				this.selected__Pattern,
			out List<BabebiDataSet.LetterOrSymbolRow>		letterOrSymbols_,
			out Dictionary<short, BabebiDataSet.SymbolRow>	ranks__symbols_,
			out List<string>								pattern_Remaining_SubStrings_	
			);
			this.letterOrSymbols__of__Pattern__UniqueKeyString	= letterOrSymbols_;
			this.ranks__symbols									= ranks__symbols_;
			this.pattern_Remaining_SubStrings					= pattern_Remaining_SubStrings_;

			/// build ou pas ranks__Letters
			if (build__ranks__Letters)
			{
				this.compute__ranks__letters__from__Pattern__UniqueKeyString();
			}

			/// affichage => event => ComputedString
			MainForm.FromPatternLetter__fill__dataGridView(this.ranks__letters, this.guiTable__FromPatternLetter);

			/// en effet il y a une tentative de calcul sur la 1ère row 
			/// grâce au binding mais plus sur les autres rows.
			if (this.ranks__letters.Count > 1)
			{ 
				this.compute__ComputedString();
			}
		}

		private void bindingSource__Pattern__CurrentChanged(object sender, EventArgs e)
		{
			if (this.dataGridView__Pattern.Focused)
			{
				DataRow guiDataRow__Pattern = ((DataRowView)(this.bindingSource__Pattern.Current)).Row; 
				
				int		selectedId = (int)(guiDataRow__Pattern["Id"]);

				this.selected__Pattern
					= this.table__Pattern
					.FindById(selectedId);
			
				this.selected__Pattern_Language
					= this.table__Pattern_Language
					.FindByPatternIdLanguageCode(selectedId, this.mainForm.Current__Language.Code);

				this.after_Pattern_selecting(true);
			}
		}

		private void textBox__Pattern__UniqueKeyString__TextChanged(object sender, EventArgs e)
		{
			bool? patternSelecting
				= this.mainForm.textBox__Pattern__UniqueKeyString__TextChanged
				(
					this.textBox__Pattern__UniqueKeyString,
					this.textBox__Pattern__Meaning,
					this.guiTable__Pattern,
					null,
				out BabebiDataSet.PatternRow			selected__Pattern_, 
				out BabebiDataSet.Pattern_LanguageRow	selected__Pattern_Language_
				);

			if (!patternSelecting.HasValue)
			{ 
				this.preventCharEntry = false;

				return;
			}

			this.preventCharEntry = patternSelecting.Value;

			this.selected__Pattern								= selected__Pattern_;
			this.selected__Pattern_Language						= selected__Pattern_Language_;

			this.after_Pattern_selecting(true);

			#region		(ancienne version)

			/*
			string pattern__UniqueKeyString = this.textBox__Pattern__UniqueKeyString.Text;

			if (string.IsNullOrEmpty(pattern__UniqueKeyString))
			{
				return;
			}

			this.textBox__Pattern__Meaning.Text = null;

			this.guiTable__Pattern.Clear();

			if (pattern__UniqueKeyString.Length < 2)
			{ 
				return;
			}
			
			DataRow[] selectedPatterns 
				= this.table__Pattern
				.Select
				(
					"UniqueKeyString LIKE '*" + pattern__UniqueKeyString + "*'"
				);

			if (selectedPatterns.Length == 1)
			{
				this.selected__Pattern	= (BabebiDataSet.PatternRow)(selectedPatterns[0]);

				this.after_Pattern_selecting(this.selected__Pattern);

				this.textBox__Pattern__UniqueKeyString	.Text	= null;
			}
			else
			{
				DataRow matchingGuiDataRow = null;

				foreach (BabebiDataSet.PatternRow selectedPattern in selectedPatterns)
				{
					BabebiDataSet.Pattern_LanguageRow selectedPattern_Language
						= this.table__Pattern_Language
						.FindByPatternIdLanguageCode
						(
							selectedPattern.Id,
							this.mainForm.Current__Language.Code
						);

					DataRow guiDataRow 
						= this.guiTable__Pattern
						.Rows
						.Add
						(
							selectedPattern.Id,
							selectedPattern.UniqueKeyString,
							selectedPattern_Language.Meaning
						);

					if (matchingGuiDataRow == null && selectedPattern.UniqueKeyString == pattern__UniqueKeyString)
					{
						matchingGuiDataRow = guiDataRow;
					}
				}

				if (matchingGuiDataRow != null)
				{
					this.after_Pattern_selecting(matchingGuiDataRow);
				}
			}
			*/

			#endregion	(ancienne version)
		}

		private void textBox__Pattern__Meaning__TextChanged(object sender, EventArgs e)
		{
			bool? patternSelecting
				= this.mainForm.textBox__Pattern__Meaning__TextChanged
				(
					this.textBox__Pattern__UniqueKeyString,
					this.textBox__Pattern__Meaning,
					this.guiTable__Pattern,
				out BabebiDataSet.PatternRow			selected__Pattern_, 
				out BabebiDataSet.Pattern_LanguageRow	selected__Pattern_Language_
				);

			if (!patternSelecting.HasValue)
			{ 
				return;
			}

			this.selected__Pattern								= selected__Pattern_;
			this.selected__Pattern_Language						= selected__Pattern_Language_;

			this.after_Pattern_selecting(true);

			#region		ancienne version

			/*
			string parent__meaning = this.textBox__Pattern__Meaning.Text;

			if (string.IsNullOrEmpty(parent__meaning))
			{
				return;
			}

			this.textBox__Pattern__UniqueKeyString.Text = null;

			this.guiTable__Pattern.Clear();

			if (parent__meaning.Length < 2)
			{
				return;
			}

			DataRow[] selectedPattern_Languages
				= this.table__Pattern_Language
				.Select
				(
					"LanguageCode = '" + this.mainForm.Current__Language.Code + "' AND Meaning LIKE '*" + parent__meaning + "*'"
				);

			if (selectedPattern_Languages.Length == 1)
			{
				this.selected__Pattern_Language = (BabebiDataSet.Pattern_LanguageRow)(selectedPattern_Languages[0]);

				this.after_Pattern_selecting(this.selected__Pattern_Language);

				this.textBox__Pattern__Meaning.Text = null;
			}
			else
			{
				DataRow matchingGuiDataRow = null;

				foreach (BabebiDataSet.Pattern_LanguageRow selectedPattern_Language in selectedPattern_Languages)
				{
					BabebiDataSet.PatternRow selectedPattern = selectedPattern_Language.PatternRow;

					DataRow guiDataRow
						= this.guiTable__Pattern
						.Rows
						.Add
						(
							selectedPattern_Language.PatternId,
							selectedPattern.UniqueKeyString,
							selectedPattern_Language.Meaning
						);

					if (matchingGuiDataRow == null && selectedPattern_Language.Meaning == parent__meaning)
					{
						matchingGuiDataRow = guiDataRow;
					}
				}

				if (matchingGuiDataRow != null)
				{
					this.after_Pattern_selecting(matchingGuiDataRow);
				}
			}
			*/

			#endregion		ancienne version
		}

		bool preventCharEntry = false;
		private void textBox__Pattern__UniqueKeyString__KeyPress(object sender, KeyPressEventArgs e)
		{
			MainForm.Searching__UniqueKeyString__KeyPress(this.preventCharEntry, e);
		}

		#endregion	selecting of the (parent) Pattern
		#region		about FromPatternLetters

		private void bindingSource__FromPatternLetter__CurrentChanged(object sender, EventArgs e)
		{
			this.mainForm.FromPatternLetter__bindingSource__CurrentChanged
			(
				this.bindingSource__FromPatternLetter,
				this.guiColumn__FromPatternLetter__Rank,				
				this.guiColumn__FromPatternLetter__LetterTypeCode,
				this.guiColumn__FromPatternLetter__LetterString,	
				this.textBox__FocusedRank,
				this.textBox__FocusedLetter,
				this.comboBox__SelectedLetter
			);
		}

		private void comboBox__SelectedLetter__SelectedIndexChanged(object sender, EventArgs e)
		{
			MainForm.FromPatternLetter__comboBox__SelectedLetter__SelectedIndexChanged
			(
				this.textBox__FocusedRank,
				this.textBox__FocusedLetter,
				this.comboBox__SelectedLetter,
				this.ranks__letters,
				this.guiTable__FromPatternLetter,
				this.guiColumn__FromPatternLetter__LetterString
			);

			this.compute__ComputedString();
		}
		
		#endregion	about FromPatternLetters

		private void compute__ComputedString()
		{
			if (this.noControl_WEM__PARENT_Pattern.HasError)
			{
				this.textBox__ComputedString.Text = null;

				return;
			}

			if (this.guiTable__FromPatternLetter.Rows.Count != this.ranks__letters.Count)
			{
				this.textBox__ComputedString.Text = null;

				return;
			}

			string computedString 
				= WordFromPattern
				.Compute_UniqueKeyString
				(
					this.pattern_Remaining_SubStrings,
					this.ranks__letters
				);

			this.textBox__ComputedString.Text = computedString;

			this.mainForm.Word__UniqueKeyString__TextChanged(this.textBox_WEM__UniqueKeyString);
		}

		private void button__CreateUpdate__Click(object sender, EventArgs e)
		{
			if (this.noControl_WEM__PARENT_Pattern.HasError)
			{ 
				this.noControl_WEM__PARENT_Pattern.ShowMessageBox();

				return;
			}
			if (this.textBox_WEM__UniqueKeyString.HasError)
			{ 
				this.textBox_WEM__UniqueKeyString.ShowMessageBox();

				return;
			}

			if (this.trueForCreate__falseForUpdate)
			{
				this.mainForm.RemovePriorWordExtensionIfAny();

				this.current__Word.ModeCode = MainForm.ModeCode_FromPattern;

				this.current__FromPattern
					= this.table__FromPattern
					.AddFromPatternRow
					(
						this.current__Word.SubscribingCode,
						this.current__Word.Id,
						this.selected__Pattern,
						this.selected__GuiHorizontalShift
					);

				this.current__WordFromPattern
					= this.table__WordFromPattern
					.AddWordFromPatternRow
					(
						this.current__Word.Id,
						MainForm.ModeCode_FromPattern,
						MainForm.SubscriberCode_Word
					);
				
				this.current__Pattern
					= this.selected__Pattern;

				this.current__Pattern_Language
					= this.selected__Pattern_Language;
				
				foreach(KeyValuePair<short, Letter> rank__letter in this.ranks__letters)
				{
					short	rank	= rank__letter.Key;
					Letter	letter	= rank__letter.Value;

					this.table__FromPatternLetter
						.AddFromPatternLetterRow
						(
							this.current__WordFromPattern.SubscribingCode,
							this.current__WordFromPattern.Id,
							rank,
							letter.TypeCode,
							letter.String
						);
				}

				this.mainForm.button__Pattern__FromPattern__CreateUpdate.Text = "UPDATE";
			}
			else
			{
				/// about parent 
				if (this.selected__Pattern != this.current__Pattern)
				{
					this.current__FromPattern.PatternRow = this.selected__Pattern;

					this.current__Pattern			= this.selected__Pattern;
					this.current__Pattern_Language	= this.selected__Pattern_Language;
				}

				/// about GuiHorizontalShift
				if 
				(selected__GuiHorizontalShift != this.current__FromPattern.GuiHorizontalShift)
				{
					this.current__FromPattern.GuiHorizontalShift = this.selected__GuiHorizontalShift;
				}

				/// adapting of the FromPatternLetters
				BabebiDataSet.FromPatternLetterRow[] fromPatternLetters
					= this.current__FromPattern.GetFromPatternLetterRows();

				/// on initialise le maxRank avec le plus grand rank de ranks__letters qui est le dernier puisque c'est un SortedDictionary.
				short maxRank = this.ranks__letters.Last().Key;

				foreach (BabebiDataSet.FromPatternLetterRow fromPatternLetterRow in fromPatternLetters)
				{
					if (maxRank < fromPatternLetterRow.Rank)
					{
						maxRank = fromPatternLetterRow.Rank;
					}
				}

				for (short rank = 1; rank <= maxRank; rank++)
				{
					Letter? letter_;
					if (this.ranks__letters.Keys.Contains(rank))
					{
						letter_ = this.ranks__letters[rank];
					}
					else
					{
						letter_ = null;
					}

					BabebiDataSet.FromPatternLetterRow fromPatternLetter = null;
					foreach (BabebiDataSet.FromPatternLetterRow fromPatternLetter_ in fromPatternLetters)
					{
						if
						(
							fromPatternLetter_.RowState != DataRowState.Detached
							&&
							fromPatternLetter_.RowState != DataRowState.Deleted
							&&
							rank == fromPatternLetter_.Rank
						)
						{
							fromPatternLetter = fromPatternLetter_;
						}
					}

					if (letter_.HasValue)
					{
						Letter letter = letter_.Value;

						if (fromPatternLetter != null)
						{
							/// ce rank doit exister et il existe déjà => update.

							fromPatternLetter.BeginEdit();

							if (fromPatternLetter.LetterTypeCode != letter.TypeCode)
							{
								fromPatternLetter.LetterTypeCode = letter.TypeCode;
							}
							if (fromPatternLetter.LetterString != letter.String)
							{
								fromPatternLetter.LetterString = letter.String;
							}

							fromPatternLetter.EndEdit();
						}
						else
						{
							/// ce rank doit exister mais il n'existe pas => Insert.

							this.table__FromPatternLetter.AddFromPatternLetterRow
							(
								this.current__WordFromPattern.SubscribingCode,
								this.current__WordFromPattern.Id,
								rank,
								letter.TypeCode,
								letter.String
							);
						}
					}
					else
					{
						if (fromPatternLetter != null)
						{
							/// ce rank ne doit pas exister mais il existe => Delete.

							this.table__FromPatternLetter.RemoveFromPatternLetterRow(fromPatternLetter);
						}
						else
						{
							/// ce rank ne doit pas exister et il n'existe pas => rien à faire.
						}
					}
				}
			}

			this.mainForm.populate__WordFromPattern(PopulatingType.SettingFieldsOnly);

			/// the target !
			Word.SetUniqueKeyString(this.mainForm.Current__Word, this.textBox__ComputedString.Text);

			this.mainForm.textBox__Word__String.Text	= this.textBox__ComputedString.Text;

			this.DialogResult = DialogResult.OK;

			this.Close();
		}
	}
}
