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__PatternByInsertion__of__Current__Word__CreateUpdate : Form
	{
		private MainForm					mainForm;
		private bool						trueForCreate__falseForUpdate;

		#region		shortcuts

		private BabebiDataSet				dataSet;
		private BabebiDataSet.LanguageRow	currentLanguage		;
		private string						currentLanguageCode	;

		/// this is the Word that is the parent/origin of the currently created/updated Pattern-ByInsertion.
		private BabebiDataSet.WordRow		current__Word;	

		#endregion	shortcuts
		#region		variables

		private int	pattern__Id = -1;
		private short selected__InsertionIndex = -1;
		private BabebiDataSet.LetterOrSymbolClusterRow		selected__LetterOrSymbolCluster = null;

		List<BabebiDataSet.LetterOrSymbolRow> letterOrSymbolList_of_the_LetterOrSymbolCluster = new List<BabebiDataSet.LetterOrSymbolRow>();
		
		#endregion	variables
		#region		error management

		private TextBox_WEM		textBox_WEM__Id;
		private TextBox_WEM		textBox_WEM__UniqueKeyString;
		private TextBox_WEM		textBox_WEM__Meaning;
																
		private ComboBox_WEM	comboBox_WEM__InsertionIndex;
		private TextBox_WEM		textBox_WEM__LetterOrSymbolClusterString;

		#endregion	error management

		#region		ctors

		public Form__PatternByInsertion__of__Current__Word__CreateUpdate(MainForm mainForm, bool trueForCreate__falseForUpdate) : this()
		{
			this.mainForm						= mainForm;
			this.trueForCreate__falseForUpdate	= trueForCreate__falseForUpdate;

			#region		shortcuts

			this.dataSet				= this.mainForm.DataSet;
			this.currentLanguage		= this.mainForm.Current__Language;
			this.currentLanguageCode	= this.mainForm.Current__Language.Code;
			this.current__Word			= this.mainForm.Current__Word;

			#endregion	shortcuts
			#region		(base)

			this.mainForm.Ctor__CreateUpdate__Pattern
			(
				this,
				this.button__CreateUpdate,
				this.button__Clone, 
				MainForm.ModeName_ByInsertion,
				this.label__Id					,
				this.label__ComputedString		,
				this.label__Meaning	,
				this.textBox__Id				,
				this.textBox__ComputedString	,
				this.textBox__Meaning	,
				true,
			out	TextBox_WEM		textBox_WEM__Id_				,
			out	TextBox_WEM		textBox_WEM__ComputedString_	,
			out	TextBox_WEM		textBox_WEM__Meaning_,
				this.trueForCreate__falseForUpdate,
			ref this.pattern__Id,
				this.mainForm.Current__Pattern__of__PatternByInsertion__of__Current__Word,					
				this.mainForm.Current__Pattern_Language__of__PatternByInsertion__of__Current__Word
			);
			this.textBox_WEM__Id				= textBox_WEM__Id_				;
			this.textBox_WEM__UniqueKeyString	= textBox_WEM__ComputedString_	;
			this.textBox_WEM__Meaning			= textBox_WEM__Meaning_;

			#endregion	(base)
			#region		(mode)

			#region		error management

			this.comboBox_WEM__InsertionIndex	 
				= new ComboBox_WEM
				(
					this.label__InsertionIndex, 
					this.comboBox__InsertionIndex, 
					"The 'Insertion Index' has not been selected.", 
					"Missing 'Insertion Index'", 
					(
						this.trueForCreate__falseForUpdate 
						? 
						null 
						: 
						MainForm.Convert__InsertionIndex__into__ComboBoxSelectedItem(this.mainForm.Current__PatternByInsertion__of__Current__Word.InsertionIndex)
					)
				);
				
			this.textBox_WEM__LetterOrSymbolClusterString
				= new TextBox_WEM
				(
					this.label__LetterOrSymbolClusterString, 
					this.textBox__LetterOrSymbolClusterString, 
					"The 'Letter or Symbol Cluster' has not been selected.", 
					"Missing 'Letter or Symbol Cluster'", 
					(
						this.trueForCreate__falseForUpdate 
						? 
						null 
						: 
						this.mainForm.Current__PatternByInsertion__of__Current__Word.LetterOrSymbolClusterRow.String
					)
				);

			#endregion	error management

			if (this.trueForCreate__falseForUpdate)
			{
				this.comboBox__InsertionIndex.SelectedIndex = 0;	/// ce choix est 'At the end' qui ne pose jamais de problème.
				this.selected__InsertionIndex = 32;
			}
			else
			{
				this.selected__InsertionIndex				= this.mainForm.Current__PatternByInsertion__of__Current__Word.InsertionIndex;
				string insertionIndexString					= MainForm.Convert__InsertionIndex__into__ComboBoxSelectedItem(this.selected__InsertionIndex);
				this.comboBox__InsertionIndex.SelectedItem	= insertionIndexString;

				this.selected__LetterOrSymbolCluster			= this.mainForm.Current__PatternByInsertion__of__Current__Word.LetterOrSymbolClusterRow;
				this.textBox__LetterOrSymbolClusterString.Text	= this.selected__LetterOrSymbolCluster.String;
			}

			#endregion	(mode)
		}

		public Form__PatternByInsertion__of__Current__Word__CreateUpdate()
		{
			InitializeComponent();
		}

		#endregion	ctors

		#region		(base) events
 
		private void button__Clone__Click(object sender, EventArgs e)
		{
			this.mainForm.Clone__Pattern
			(
				null,
				this.textBox__Meaning,
				true,
				this.mainForm.Current__Pattern__of__PatternByInsertion__of__Current__Word,					
				this.mainForm.Current__Pattern_Language__of__PatternByInsertion__of__Current__Word
			);
		}

		#region		Pattern__Id

		private void textBox__Pattern__Id__KeyPress(object sender, KeyPressEventArgs e)
		{
			MainForm.Integer__KeyPress(e);
		}
		private void textBox__Pattern__Id__TextChanged(object sender, EventArgs e)
		{
			if (this.textBox_WEM__Id != null)
			{
				this.mainForm.Pattern__Id__TextChanged(this.textBox_WEM__Id, ref this.pattern__Id);
			}
		}
		private void textBox__Pattern__Id__Leave(object sender, EventArgs e)
		{
			if (this.textBox_WEM__Id.HasError && !string.IsNullOrEmpty(textBox__Id.Text))
			{
				this.textBox_WEM__Id.ShowMessageBox();
			}
		}

		#endregion	Pattern__Id
		#region		Word_Language__Meaning

		private void textBox__Word_Language__Meaning__TextChanged(object sender, EventArgs e)
		{
			if (this.textBox_WEM__Meaning != null)
			{
				this.mainForm.Pattern__Meaning__TextChanged(this.textBox_WEM__Meaning);
			}
		}

		private void textBox__Word_Language__Meaning__Leave(object sender, EventArgs e)
		{
			if (this.textBox_WEM__Meaning.HasError && !string.IsNullOrEmpty(textBox__Meaning.Text))
			{
				this.textBox_WEM__Meaning.ShowMessageBox();
			}
		}

		#endregion	Word_Language__Meaning
		#region		ComputedString

		private void textBox__Word__ComputedString__TextChanged(object sender, EventArgs e)
		{
			if (this.textBox_WEM__UniqueKeyString != null)
			{
				this.mainForm.Pattern__UniqueKeyString__TextChanged(this.textBox_WEM__UniqueKeyString);
			}
		}

		#endregion	ComputedString

		#endregion	(base) events
		#region		(mode events)

		private void comboBox__InsertionIndex__SelectedIndexChanged(object sender, EventArgs e)
		{
			this.mainForm.ComboBox__InsertionIndex__SelectedIndexChanged
				(
					this.comboBox_WEM__InsertionIndex,
					Convert.ToInt16( this.mainForm.Current__Word.UniqueKeyString.Length ),
				ref this.selected__InsertionIndex
				);

			this.compute__ComputedString();

			#region		(ancienne version)
			/*
			this.selected__InsertionIndex
				= MainForm.Convert__ComboBoxSelectedItem__into__InsertionIndex
				(
					(string)
					(this.comboBox__InsertionIndex.SelectedItem)
				);

			if
			(
				this.selected__InsertionIndex != 32
				&&
				this.selected__InsertionIndex > this.current__Word.UniqueKeyString.Length
			)
			{
				string errorMessage
					= "The selected 'Insertion Index' (" + this.selected__InsertionIndex.ToString() 
					+ ") is too high because the length of 'Unique Key String' of the parent Word is only " 
					+ this.current__Word.UniqueKeyString.Length.ToString() + ".";

				this.comboBox_WEM__InsertionIndex.SetError(errorMessage, "Too high Insertion Index");

				this.textBox__Pattern__ComputedString.Text = null;

				this.comboBox_WEM__InsertionIndex.ShowMessageBox();

				return;
			}
			else
			{
				this.comboBox_WEM__InsertionIndex.ClearError();

				this.compute__ComputedString();
			}
			*/
			#endregion	(ancienne version)
		}

		private void textBox__LetterClusterString__TextChanged(object sender, EventArgs e)
		{
			this.mainForm.textBox__LetterOrSymbolClusterString__TextChanged
			(
				this.textBox_WEM__LetterOrSymbolClusterString, 
			ref this.selected__LetterOrSymbolCluster,
				this.letterOrSymbolList_of_the_LetterOrSymbolCluster
			);

			this.compute__ComputedString();

			#region		(ancienne version)
			/*
			string letterClusterString = this.textBox__LetterOrSymbolClusterString.Text;

			this.ranks__letterOrSymbols.Clear();

			if
			(
				!this.trueForCreate__falseForUpdate
				&&
				letterClusterString == this.mainForm.Current__WordByInsertion__of__Current__Word.LetterClusterRow.String
			)
			{
				this.selected__LetterOrSymbolCluster = this.mainForm.Current__WordByInsertion__of__Current__Word.LetterClusterRow;

				this.textBox_WEM__LetterOrSymbolClusterString.ClearError();
			}
			else
			{
				DataRow[] letterClusterdataRows 
					= this.dataSet.LetterCluster.Select("String = '" + letterClusterString + "'");

				if (letterClusterdataRows.Length == 0)
				{
					/// the LetterCluster does not exit yet => so, is the input string valid or not?

					#region		check if the LetterCluster string only contains valid Letters

					short rank = -1;
					for (int i = 0; i < letterClusterString.Length; i++)
					{
						rank++;

						char thisChar = letterClusterString[i];

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

							string doubleLetterString = new string(new char[] { thisChar, nextChar });

							BabebiDataSet.LetterRow doubleLetter
								= this.dataSet.Letter.FindByString(doubleLetterString);

							if (doubleLetter != null)
							{
								this.ranks__letterOrSymbols.Add(rank, doubleLetter);

								rank++;

								continue;
							}
						}

						string monoLetterString = new string(new char[] { thisChar });

						BabebiDataSet.LetterRow monoLetter
							= this.dataSet.Letter.FindByString(monoLetterString);

						if (monoLetter == null)
						{
							this.textBox__Pattern__ComputedString.Text = null;

							this.textBox_WEM__LetterOrSymbolClusterString 
								.SetError
								(
									"The 'Letter Cluster' string contains the invalid character: '" + monoLetterString + "'.",
									"Invalid character"
								);


							return;
						}
						else
						{
							ranks__letterOrSymbols.Add(rank, monoLetter);
						}
					}

					this.selected__LetterOrSymbolCluster = null;    /// will be created while click the UPDATE button, which is a proof that this value is not so important...

					this.textBox_WEM__LetterOrSymbolClusterString.ClearError();

					#endregion	check if the LetterCluster string only contains valid Letters
				}
				else if (letterClusterdataRows.Length == 1)
				{
					this.selected__LetterOrSymbolCluster = (BabebiDataSet.LetterClusterRow)(letterClusterdataRows[0]); 
				}
				else
				{
					throw new Exception();
				}
			}

			this.compute__ComputedString();
			*/
			#endregion	(ancienne version)
		}

		#endregion	(mode events)

		public void compute__ComputedString()
		{
			#region		trapping error about InsertionIndex & LetterClusterString

			if
			(
				this.comboBox_WEM__InsertionIndex.HasError
				||
				this.textBox_WEM__LetterOrSymbolClusterString.HasError
			)
			{
				this.textBox__ComputedString.Text = null;
				
				return;
			}

			#endregion	trapping error about InsertionIndex & LetterClusterString

			string parentString					= this.current__Word.UniqueKeyString;
			string letterOrSymbolClusterString	= this.textBox__LetterOrSymbolClusterString.Text;

			#region		trapping error about a__a_OR_e__e_OR_o__o

			if 
			(
				this.mainForm.Is_a__a_OR_e__e_OR_o__o
				(
					parentString, 
					letterOrSymbolClusterString,
					this.selected__InsertionIndex,
					this.textBox_WEM__UniqueKeyString
				)
			)
			{
				return;
			}

			#endregion	trapping error about a__a_OR_e__e_OR_o__o
			#region		current__Word__UniqueKeyString.Length + letterClusterString.Length > 32 ?

			if(parentString.Length + letterOrSymbolClusterString.Length > 32)
			{
				this.textBox__ComputedString.Text = null;

				string errorMessage
					= "The sum of the lenghts of:\n" 
					+ "   - the current Word 'Unique Key String' and\n" 
					+ "   - the 'Letter Cluster String'\n" 
					+ "is bigger than 32, which would produce a too long Word (Word max. lenght = 32).";

				this.textBox_WEM__UniqueKeyString.SetError(errorMessage, "Too long (computed) 'Unique Key String'");

				return;
			}

			#endregion	current__Word__UniqueKeyString.Length + letterClusterString.Length > 32 ?

			string computedString 
				= WordByInsertion.Compute_UniqueKeyString
				(
					this.current__Word, 
					this.selected__InsertionIndex, 
					letterOrSymbolClusterString
				);

			/// on affiche le resultat même s'il cause une error.
			this.textBox__ComputedString.Text = computedString;	
			
			this.mainForm.Pattern__UniqueKeyString__TextChanged(this.textBox_WEM__UniqueKeyString);
		}

		private void button__CreateUpdate__Click(object sender, EventArgs e)
		{
			#region		checking

			if (this.textBox_WEM__Id.HasError)
			{
				this.textBox_WEM__Id.ShowMessageBox();

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

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

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

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

				return;
			}

			#endregion	checking

			/// usefull in both Create or Update modes.
			if (this.selected__LetterOrSymbolCluster == null)
			{
				this.selected__LetterOrSymbolCluster 
					= this.mainForm.build__LetterOrSymbolCluster
					(this.letterOrSymbolList_of_the_LetterOrSymbolCluster);
			}

			if (this.trueForCreate__falseForUpdate)
			{
				#region		(base)

				this.mainForm.Create__Pattern
				(
					this.pattern__Id,
					this.textBox__ComputedString.Text,
					this.textBox__Meaning.Text,
				out BabebiDataSet.WordOrPatternRow		current__WordOrPattern_,
				out BabebiDataSet.PatternRow			current__Pattern_,
				out BabebiDataSet.Pattern_LanguageRow	current__Pattern_Language_,
					MainForm.ModeCode_ByInsertion
				);

				this.mainForm.Current__WordOrPattern__of__PatternByInsertion__of__Current__Word		= current__WordOrPattern_;
				this.mainForm.Current__Pattern__of__PatternByInsertion__of__Current__Word			= current__Pattern_;
				this.mainForm.Current__Pattern_Language__of__PatternByInsertion__of__Current__Word	= current__Pattern_Language_;

				#endregion	(base)
				#region		(mode)

				this.mainForm.Current__PatternByInsertion__of__Current__Word
					= this.dataSet.PatternByInsertion
					.AddPatternByInsertionRow
					(
						this.pattern__Id,
						this.current__Word.WordOrPatternRowParent.SubscriberCode,
						this.current__Word.WordOrPatternRowParent.SubscriberId,
						this.selected__InsertionIndex,
						this.selected__LetterOrSymbolCluster,
						MainForm.ModeCode_ByInsertion
					);

				#endregion	(mode)
			}
			else
			{
				#region		(base)

				this.mainForm.Update__Pattern
				(
					this.pattern__Id,
					this.textBox__ComputedString.Text,
					this.textBox__Meaning.Text,
					this.mainForm.Current__WordOrPattern__of__PatternByInsertion__of__Current__Word,
					this.mainForm.Current__Pattern__of__PatternByInsertion__of__Current__Word,
					this.mainForm.Current__Pattern_Language__of__PatternByInsertion__of__Current__Word
				);

				#endregion	(base)
				#region		(mode)

				/// about InsertionIndex
				if (this.selected__InsertionIndex != this.mainForm.Current__PatternByInsertion__of__Current__Word.InsertionIndex)
				{
					this.mainForm.Current__PatternByInsertion__of__Current__Word.InsertionIndex = this.selected__InsertionIndex;
				}

				/// about LetterOrSymbolCluster
				this.mainForm.Set_LetterOrSymbolCluster_and_remove_prior_if_not_used_by_other
				(	
					this.selected__LetterOrSymbolCluster,
					this.mainForm.Current__PatternByInsertion__of__Current__Word
				);

				#endregion	(mode)
			}

			this.DialogResult = DialogResult.OK;

			this.Close();
		}

		private void button__Retrieve__Click(object sender, EventArgs e)
		{
			this.textBox__Meaning.Text = this.mainForm.Current__Word_Language.Meaning;
		}
	}
}
