using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace Babebi4
{
	public partial class Form__PatternFromPattern__CreateUpdate : Form
	{
		private MainForm		mainForm;
		private BabebiDataSet	dataSet;

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

		#region		shortcuts

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

		private BabebiDataSet.PatternDataTable				table__Pattern				{ get { return this.dataSet.Pattern; } }
		private BabebiDataSet.Pattern_LanguageDataTable		table__Pattern_Language		{ get { return this.dataSet.Pattern_Language; } }
		private BabebiDataSet.PatternFromPatternDataTable	table__PatternFromPattern	{ get { return this.dataSet.PatternFromPattern; } }

		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; } }

		#endregion	shortcuts
		#region		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	gui tables
		#region		current__#s

		/// attention : cette Row correspond au (parent) Pattern du FromPattern que l'on cherche à updater (donc pas au Pattern lui-même).
		private BabebiDataSet.PatternRow			selected__Pattern__PARENT			= null;
		private BabebiDataSet.Pattern_LanguageRow	selected__Pattern_Language__PARENT	= null;

		private BabebiDataSet.PatternRow			current__Pattern								
		{
			get
			{
				return this.mainForm.Current__Pattern;
			}
		}
		private BabebiDataSet.PatternFromPatternRow	current__PatternFromPattern						
		{
			get
			{
				return this.mainForm.Current__PatternFromPattern;
			}
			set
			{
				this.mainForm.Current__PatternFromPattern = value;
			}
		}
		private BabebiDataSet.FromPatternRow		current__FromPattern							
		{
			get
			{
				return this.mainForm.Current__FromPattern__of__PatternFromPattern;
			}
			set
			{
				this.mainForm.Current__FromPattern__of__PatternFromPattern = value;
			}
		}

		/// lors de l'Update, c'est la valeur précédente.
		private BabebiDataSet.PatternRow			current__Pattern__of__PatternFromPattern__PARENT
		{
			get
			{
				return this.mainForm.Current__Pattern__of__PatternFromPattern__Parent;
			}
		}

		#endregion	current__#s
		#region		variables

		private short selected__GuiHorizontalShift = -1;	/// means 'undefined'

		/// about the selected PARENT Pattern.
		private List<BabebiDataSet.LetterOrSymbolRow>		letterOrSymbols_of__PARENT__Pattern__UniqueKeyString;
		private Dictionary<short, BabebiDataSet.SymbolRow>	ranks__symbols;
		private List<string>								PARENT__Pattern__remaining__SubStrings;

		/// about the Pattern being built.
		private List<BabebiDataSet.LetterOrSymbolRow>		letterOrSymbols_of_Pattern__UniqueKeyString;
		private SortedDictionary<short, Letter>				ranks__letters;

		#endregion	variables
		#region		error management

		private TextBox_WEM		textBox_WEM__UniqueKeyString;
		private NoControl_WEM	noControl_WEM__Pattern__PARENT	;
		private ComboBox_WEM	comboBox_WEM__GuiHorizontalShift;

		#endregion	error management

		#region		ctors

		public Form__PatternFromPattern__CreateUpdate(MainForm mainForm) : this()
		{
			this.mainForm	= mainForm;
			this.dataSet	= this.mainForm.DataSet;
			#region		error management

			this.textBox_WEM__UniqueKeyString 
				= new TextBox_WEM
				(
					this.label__ComputedString,
					this.textBox__ComputedString,
					"The 'Computed String' has not been computed.",
					"Empty 'Computed String'",
					this.current__Pattern.UniqueKeyString
				);

			this.noControl_WEM__Pattern__PARENT	= new NoControl_WEM("The parent Pattern has to be selected.", "Missing parent Pattern");

			this.comboBox_WEM__GuiHorizontalShift 
				= new ComboBox_WEM
				(
					this.label__GuiHorizontalShift,
					this.comboBox__GuiHorizontalShift,
					"The 'Gui Horizontal Shift' has to be selected.",
					"Missing 'Gui Horizontal Shift'",
					( this.trueForCreate__falseForUpdate ? null : this.current__FromPattern.GuiHorizontalShift.ToString() )
				);

			#endregion	error management
			#region		about the guiTables

			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	about the guiTables
			#region		analyse the UKS of the Pattern
			
			this.letterOrSymbols_of_Pattern__UniqueKeyString = new List<BabebiDataSet.LetterOrSymbolRow>();

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

				this.textBox_WEM__UniqueKeyString.ShowMessageBox();

				this.button__CreateUpdate.Visible = false;

				return;
			}

			#endregion	analyse the UKS of the Pattern

			if (this.current__PatternFromPattern == null)
			{
				#region		CREATE case

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

				this.comboBox__GuiHorizontalShift.SelectedIndex = 0;
				this.selected__GuiHorizontalShift = 0;

				this.button__CreateUpdate.Text = "CREATE";

				#endregion	CREATE case
			}
			else
			{
				#region		UPDATE case

				#region		GuiHorizontalShift

				this.selected__GuiHorizontalShift				= this.mainForm.Current__FromPattern__of__PatternFromPattern.GuiHorizontalShift;
				this.comboBox__GuiHorizontalShift.SelectedItem	= this.mainForm.textBox__Pattern__FromPattern__GuiHorizontalShift.Text;

				#endregion	GuiHorizontalShift
				#region		initialize ranks__letterStrings from current__FromPatternLetters

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

				#endregion	initialize ranks__letterStrings from current__FromPatternLetters
				#region		Pattern__PARENT

				this.selected__Pattern__PARENT			= this.mainForm.Current__Pattern__of__PatternFromPattern__Parent;
				this.selected__Pattern_Language__PARENT = this.mainForm.Current__Pattern_Language__of__PatternFromPattern__Parent;

				this.after_Pattern_selecting(false);

				#endregion	Pattern__PARENT

				#endregion	UPDATE case
			}
		}

		public Form__PatternFromPattern__CreateUpdate()
		{
			InitializeComponent();
		}

		#endregion	ctors

		#region		selecting of the (parent) Pattern

		private void compute__ranks__letters__from__Pattern__UniqueKeyString()
		{
			#region		matching ?
			
			bool matching = true;   

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

			int letterOrSymbols_of_Pattern__UniqueKeyString__Count 
				= this.letterOrSymbols_of_Pattern__UniqueKeyString.Count;

			int letterOrSymbols_of__PARENT__Pattern__UniqueKeyString__Count 
				= this.letterOrSymbols_of__PARENT__Pattern__UniqueKeyString.Count;

			if 
			(
				letterOrSymbols_of__PARENT__Pattern__UniqueKeyString__Count 
				!= 
				letterOrSymbols_of_Pattern__UniqueKeyString__Count
			)
			{
				matching = false;  
			}
			else
			{
				/// rank n'est pas un char index.
				/// rank est le quantième symbole rencontré dans la UKS du PARENT pattern.
				/// rank est 1-based pour une raison esthétique d'affichage dans la DGV Letter à droite.
				short rank = 0;

				for (short i = 0; i < letterOrSymbols_of_Pattern__UniqueKeyString__Count; i++)
				{
					#region		about 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;
					}
					else
					{
						throw new Exception(letterOrSymbol__Pattern.ModeCode);
					}

					#endregion	about Pattern
					#region		about PARENT Pattern

					BabebiDataSet.LetterOrSymbolRow letterOrSymbol__PARENT__Pattern 
						= this.letterOrSymbols_of__PARENT__Pattern__UniqueKeyString[i];

					BabebiDataSet.LetterRow letter__PARENT__Pattern;
					BabebiDataSet.SymbolRow symbol__PARENT__Pattern;

					string typeCode__letterOrSymbol__PARENT__Pattern;
					if (letterOrSymbol__PARENT__Pattern.ModeCode == MainForm.ModeCode_Letter)
					{
						letter__PARENT__Pattern = this.table__Letter.FindByString(letterOrSymbol__PARENT__Pattern.String);
						symbol__PARENT__Pattern = null;

						typeCode__letterOrSymbol__PARENT__Pattern = letter__PARENT__Pattern.TypeCode;
					}
					else if (letterOrSymbol__PARENT__Pattern.ModeCode == MainForm.ModeCode_Symbol)
					{
						letter__PARENT__Pattern = null;
						symbol__PARENT__Pattern = this.table__Symbol.FindByString(letterOrSymbol__PARENT__Pattern.String);

						typeCode__letterOrSymbol__PARENT__Pattern = symbol__PARENT__Pattern.TypeCode;

						rank++;
					}
					else
					{
						throw new Exception(letterOrSymbol__PARENT__Pattern.ModeCode);
					}

					#endregion	about PARENT Pattern
					#region		analyse

					if (typeCode__letterOrSymbol__PARENT__Pattern != typeCode__letterOrSymbol__Pattern)
					{
						matching = false;   /// les deux lettres/symboles doivent être du même type (voyelle ou consonne).
					}
					else
					{
						if (letter__Pattern != null)
						{
							if (letter__PARENT__Pattern != null)
							{
								if (letter__Pattern.String != letter__PARENT__Pattern.String)
								{
									matching = false;   /// les 2 lettres doivent être identiques.
								}
							}
							else
							{
								/// on a ici une substitution de symbole par une lettre : OK.

								candidate__ranks__letters.Add(rank, new Letter(letter__Pattern.TypeCode, letter__Pattern.String));
							}
						}
						else if (symbol__Pattern != null)
						{
							if (symbol__PARENT__Pattern != null)
							{
								/// on a ici deux symboles (égaux car de même type) : OK.
							}
							else
							{
								matching = false;   /// impossible : une lettre du parent pattern ne peut pas devenir un symbole dans le pattern.
							}
						}
					}

					#endregion	analyse
				}
			}

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

				return;
			}
			else
			{
				candidate__ranks__letters.Clear();
				candidate__ranks__letters = null;
			}

			#endregion	matching ?

			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;
				}
			}
						
			for (short rank = 1; rank <= max__of__both__ranks; rank++)
			{
				BabebiDataSet.SymbolRow symbol;
				if (this.ranks__symbols.Keys.Contains(rank))
				{
					symbol = this.ranks__symbols[rank];
				}
				else
				{ 
					symbol = null;
				}

				if (symbol != null)
				{
					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 == this.mainForm.FirstVowel.TypeCode)
							{
								letter.TypeCode = this.mainForm.FirstVowel.TypeCode;
								letter.String	= this.mainForm.FirstVowel.String;
							}
							else if (symbol.TypeCode == this.mainForm.FirstConsonant.TypeCode)
							{
								letter.TypeCode = this.mainForm.FirstConsonant.TypeCode;
								letter.String	= this.mainForm.FirstConsonant.String;
							}
							else
							{
								throw new Exception();
							}
						}
					}
					else
					{
						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
				{
					if (this.ranks__letters.Keys.Contains(rank))
					{
						/// il faut supprimer cette row surnuméraire car associée à aucun Symbol.

						this.ranks__letters.Remove(rank);
					}
					else
					{
						/// rien à faire mais if faut aller chercher la prochaine Letter à deleter.
					}
				}
			}
		}

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

			/// peinture
			this.textBox__SelectedPattern__UniqueKeyString	.Text = this.selected__Pattern__PARENT			.UniqueKeyString;
			this.textBox__SelectedPattern__Meaning			.Text = this.selected__Pattern_Language__PARENT	.Meaning;
			this.textBox__SelectedPattern__Id				.Text = this.selected__Pattern__PARENT			.Id.ToString();

			/// analyse
			Pattern.Analyse__Pattern__UniqueKeyString
			(
				this.selected__Pattern__PARENT,
			out List<BabebiDataSet.LetterOrSymbolRow>		letterOrSymbols_,
			out Dictionary<short, BabebiDataSet.SymbolRow>	ranks__symbols_,
			out List<string>								remaining__SubStrings_	
			);
			this.letterOrSymbols_of__PARENT__Pattern__UniqueKeyString	= letterOrSymbols_;
			this.ranks__symbols											= ranks__symbols_;
			this.PARENT__Pattern__remaining__SubStrings					= 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 bool preventCharEntry = false;
		private void textBox__Pattern__UniqueKeyString__KeyPress(object sender, KeyPressEventArgs e)
		{
			MainForm.Searching__UniqueKeyString__KeyPress(this.preventCharEntry, e);
		}

		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,
					this.current__Pattern.UniqueKeyString,
				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__PARENT			= selected__Pattern_;
			this.selected__Pattern_Language__PARENT	= selected__Pattern_Language_;

			this.after_Pattern_selecting(true);
		}

		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__PARENT			= selected__Pattern_;
			this.selected__Pattern_Language__PARENT	= selected__Pattern_Language_;

			this.after_Pattern_selecting(true);
		}

		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 = guiDataRow__Pattern.Field<int>(this.guiColumn__Pattern__Id);

				this.selected__Pattern__PARENT
					= this.table__Pattern
					.FindById(selectedId);
			
				this.selected__Pattern_Language__PARENT
					= this.table__Pattern_Language
					.FindByPatternIdLanguageCode(selectedId, this.mainForm.Current__Language.Code);

				this.after_Pattern_selecting(true);
			}
		}

		#endregion	selecting of the (parent) Pattern

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

		#region		about FromPatternLetter

		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();
		}

		private void button__Delete__FromPatternLetter_Click(object sender, EventArgs e)
		{
			MainForm.Button__PatternFromPattern__FromPatternLetter__Delete__Click
			(
				this.textBox__FocusedRank,
				this.textBox__FocusedLetter,
				this.comboBox__SelectedLetter,
				this.ranks__letters,
				this.guiTable__FromPatternLetter
			);
		}
		
		private void button__Restore__FromPatternLetter_Click(object sender, EventArgs e)
		{
			this.compute__ranks__letters__from__Pattern__UniqueKeyString();

			/*
			if (this.trueForCreate__falseForUpdate)
			{
			}
			else
			{ 
				FromPattern_.Restore__ranks__letters__from__FromPatternLetters(this.current__FromPattern, this.ranks__letters);
			}
			*/

			MainForm.FromPatternLetter__fill__dataGridView(this.ranks__letters, this.guiTable__FromPatternLetter);

			this.compute__ComputedString();
		}

		#endregion	about FromPatternLetter

		public void compute__ComputedString()
		{
			if (this.noControl_WEM__Pattern__PARENT.HasError)
			{
				this.textBox__ComputedString.Text = null;

				return;
			}

			string computedString 
				= PatternFromPattern
				.Compute_UniqueKeyString
				(
					this.PARENT__Pattern__remaining__SubStrings,
					this.ranks__symbols,
					this.ranks__letters
				);

			this.textBox__ComputedString.Text = computedString;

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

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

				return;
			}

			if (this.trueForCreate__falseForUpdate)
			{
				/// where the prior extension (if any) has to be removed.
				this.mainForm.RemovePriorPatternExtensionIfAny();

				this.current__Pattern.ModeCode = MainForm.ModeCode_FromPattern;

				this.mainForm.PatternFromPattern
				(
					this.current__Pattern.Id,
					this.selected__Pattern__PARENT,
					this.selected__GuiHorizontalShift,
					this.ranks__letters,
				out BabebiDataSet.FromPatternRow		current__FromPattern_,
				out BabebiDataSet.PatternFromPatternRow	current__PatternFromPattern_
				);
				this.current__FromPattern			= current__FromPattern_;
				this.current__PatternFromPattern	= current__PatternFromPattern_;

				this.mainForm.Current__Pattern__of__PatternFromPattern__Parent			= this.selected__Pattern__PARENT;
				this.mainForm.Current__Pattern_Language__of__PatternFromPattern__Parent	= this.selected__Pattern_Language__PARENT;

				this.mainForm.button__Pattern__FromPattern__CreateUpdate.Text = "UPDATE";

				#region		(old version)
				/*
				this.current__FromPattern
					= this.table__FromPattern
					.AddFromPatternRow
					(
						this.current__Pattern.SubscribingCode,
						this.current__Pattern.Id,
						this.selected__Pattern__PARENT,
						this.selected__GuiHorizontalShift
					);

				this.current__PatternFromPattern
					= this.table__PatternFromPattern
					.AddPatternFromPatternRow
					(
						this.current__Pattern.Id,
						MainForm.ModeCode_FromPattern,
						MainForm.SubscriberCode_Pattern
					);

				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__PatternFromPattern.SubscribingCode,
							this.current__PatternFromPattern.Id,
							rank,
							letter.TypeCode,
							letter.String
						);
				}
				*/
				#endregion	(old version)
			}
			else
			{
				#region		UPDATE case

				/// about PARENT pattern 
				if (this.selected__Pattern__PARENT != this.current__Pattern__of__PatternFromPattern__PARENT)
				{
					this.mainForm.Current__FromPattern__of__PatternFromPattern.PatternRow	= this.selected__Pattern__PARENT;

					this.mainForm.Current__Pattern__of__PatternFromPattern__Parent			= this.selected__Pattern__PARENT;
					this.mainForm.Current__Pattern_Language__of__PatternFromPattern__Parent	= this.selected__Pattern_Language__PARENT;
				}

				/// about GuiHorizontalShift
				if ((string)(this.comboBox__GuiHorizontalShift.SelectedItem) != this.mainForm.textBox__Pattern__FromPattern__GuiHorizontalShift.Text)
				{
					this.mainForm.Current__FromPattern__of__PatternFromPattern.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.

							if (fromPatternLetter.LetterTypeCode != letter.TypeCode)
							{
								fromPatternLetter.LetterTypeCode = letter.TypeCode;
							}
							if (fromPatternLetter.LetterString != letter.String)
							{
								fromPatternLetter.LetterString = letter.String;
							}
						}
						else
						{
							/// ce rank doit exister mais il n'existe pas => Insert.

							this.table__FromPatternLetter.AddFromPatternLetterRow
							(
								this.current__PatternFromPattern.SubscribingCode,
								this.current__PatternFromPattern.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.
						}
					}
				}

				#endregion	UPDATE case
			}

			/// the target !
			Pattern.SetUniqueKeyString(this.mainForm.Current__Pattern, this.textBox__ComputedString.Text);
		//	this.mainForm.Current__Pattern.UniqueKeyString			= this.textBox__ComputedString.Text;

			this.mainForm.textBox__Pattern__UniqueKeyString.Text	= this.textBox__ComputedString.Text;

			this.DialogResult = DialogResult.OK;

			this.Close();
		}
	}
}
