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
	{
		private void remove__WordConcatenated()
		{
			this.DataSet.WordConcatenated.RemoveWordConcatenatedRow(this.Current__WordConcatenated);
			
			/// by cascading, all the links to sub-words are also removed.

			this.Current__Word.ModeCode = MainForm.ModeCode_NotDefined;

			this.populate__WordConcatenated(PopulatingType.Cleaning);
		}

		private void populate__WordConcatenated(PopulatingType populatingType)
		{
			if (populatingType == PopulatingType.Cleaning)
			{
				this.Current__WordConcatenated = null;
				
				this.Current__WordConcatenatedComponent						= null;
				this.Current__Word__of__WordConcatenatedComponent			= null;
				this.Current__Word_Language__of__WordConcatenatedComponent	= null; 

				return;
			}

			/// il n'y a pas besoin de séter les 3 rows car cela se fait automatiquement 
			/// dans l'event du binding de la guidataview.

			if (this.Current__Word.ModeCode == MainForm.ModeCode_Concatenated)
			{
				/// UPDATE Case
				
				this.Current__WordConcatenated 
					= this.DataSet.WordConcatenated
					.FindById
					(this.Current__Word.Id);

				this.Compute__ConcatenatedString();
			}
			else
			{
				/// CREATE case : 
				/// 
				/// A la différence des autres Modes, la Row Concatenated ne contient aucun information
				/// à saisir : elle sert juste de parent row aux WordConcatenatedComponants. Ceci implique que l'on peut 
				/// la créer manu militari (ici) dés que l'on en a besoin.

				this.Current__Word.ModeCode = MainForm.ModeCode_Concatenated;

				this.Current__WordConcatenated 
					= this.babebiDataSet.WordConcatenated
					.AddWordConcatenatedRow
					(
						this.Current__Word.Id, 
						MainForm.ModeCode_Concatenated
					);
			}

			this.guiTable__WordConcatenatedComponent.Populate();		
		}

		private		bool hasError__WordConcatenatedComputedString_ = false;
		internal	bool HasError__WordConcatenatedComputedString
		{
			get { return this.hasError__WordConcatenatedComputedString_; }
			set
			{
				this.hasError__WordConcatenatedComputedString_ = value;

				if (this.hasError__WordConcatenatedComputedString_)
				{
					this.label__WordConcatenated__ComputedString.ForeColor = Color.Red;

					this.textBox__WordConcatenated__ComputedString.BackColor = SystemColors.Control;
					this.textBox__WordConcatenated__ComputedString.ForeColor = Color.Red;
				}
				else
				{
					if (this.textBox__WordConcatenated__ComputedString.Text == this.Current__Word.UniqueKeyString)
					{
						this.label__WordConcatenated__ComputedString.ForeColor = Color.Black;

						this.textBox__WordConcatenated__ComputedString.BackColor = SystemColors.Control;
						this.textBox__WordConcatenated__ComputedString.ForeColor = Color.Black;
					}
					else
					{
						this.label__WordConcatenated__ComputedString.ForeColor = Color.Blue;

						this.textBox__WordConcatenated__ComputedString.BackColor = SystemColors.Control;
						this.textBox__WordConcatenated__ComputedString.ForeColor = Color.Blue;
					}
				}
			}
		}

		internal void Compute__ConcatenatedString()
		{
			string uniqueKeyString = WordConcatenated.Compute_UniqueKeyString(this.Current__WordConcatenated);

			this.textBox__WordConcatenated__ComputedString.Text = uniqueKeyString;

			if (this.textBox__WordConcatenated__ComputedString.Text.Length > 32)
			{
				this.HasError__WordConcatenatedComputedString = true;

				MessageBox.Show
				(
					"The length of the concatenated string is too long (the maximum is 32)",
					"String too long",
					MessageBoxButtons.OK,
					MessageBoxIcon.Error
				); 
				return;
			}

			if (uniqueKeyString != this.Current__Word.UniqueKeyString)
			{
				BabebiDataSet.WordRow[] alreadyExistingWords
					=
					(BabebiDataSet.WordRow[])
					(this.DataSet.Word.Select("UniqueKeyString = '" + uniqueKeyString + "'"));

				if (alreadyExistingWords.Length == 1)
				{
					this.HasError__WordConcatenatedComputedString = true;

					BabebiDataSet.WordRow alreadyExistingWord = alreadyExistingWords[0];

					BabebiDataSet.Word_LanguageRow alreadyExistingWord_Language 
						= this.DataSet.Word_Language.FindByWordIdLanguageCode
						(
							alreadyExistingWord.Id, 
							this.Current__Language.Code
					);

					/// le if(...) pour eviter, au premier componant, de dire qu'il existe déjà...
					if (this.Current__WordConcatenated.GetWordConcatenatedComponentRows().Length > 1)
					{
						MessageBox.Show
						(
							"The concatenated string is already the one of an existing Word (Id = '" +
							alreadyExistingWord.Id.ToString() + "' and Meaning = '" +
							alreadyExistingWord_Language.Meaning + "').",
							"Already existing String",
							MessageBoxButtons.OK,
							MessageBoxIcon.Error
						);
					}

					return;
				}
			}
			
			this.HasError__WordConcatenatedComputedString = false;
		}

		private void button__WordConcatenatedComponent__CreateUpdate__Click()
		{
			Form__WordConcatenatedComponent__Create form = new Form__WordConcatenatedComponent__Create(this, true);

			DialogResult dialogResult = form.ShowDialog();
			if(dialogResult == DialogResult.Cancel)
			{
				return;
			}

			DataRow focusedGuiDataRow 
				= this.guiTable__WordConcatenatedComponent
				.Find(this.Current__WordConcatenatedComponent.Rank);

			FocusGridRow(this.BindingSource__WordConcatenatedComponent, focusedGuiDataRow);
		}
		private void button__WordConcatenatedComponent__Create__Click(object sender, EventArgs e)
		{
			this.button__WordConcatenatedComponent__CreateUpdate__Click();
		}


		private void button__WordConcatenated__Update__UniqueKeyString__Click(object sender, EventArgs e)
		{
			Word.SetUniqueKeyString(this.Current__Word, this.textBox__WordConcatenated__ComputedString.Text);
		//	this.Current__Word.UniqueKeyString	= this.textBox__WordConcatenated__ComputedString.Text;

			this.textBox__Word__String.Text		= this.Current__Word.UniqueKeyString;

			this.label__WordConcatenated__ComputedString.ForeColor = Color.Black;
			this.textBox__WordConcatenated__ComputedString.BackColor = Color.White;
			this.textBox__WordConcatenated__ComputedString.ForeColor = Color.Black;

		}

		private void button__WordConcatenatedComponent__Update_Click(object sender, EventArgs e)
		{
			Form__WordConcatenatedComponent__Create form = new Form__WordConcatenatedComponent__Create(this, false);

			form.ShowDialog();
		}

		private void button__WordConcatenatedComponent__Delete_Click(object sender, EventArgs e)
		{
			Form__WordConcatenatedComponent__Delete form = new Form__WordConcatenatedComponent__Delete(this);

			form.ShowDialog();
		}

		private void button__WordConcatenate__Up_Click(object sender, EventArgs e)
		{
			if (this.Current__WordConcatenatedComponent == null)
			{
				return;
			}

			short selectedRank = this.Current__WordConcatenatedComponent.Rank;

			BabebiDataSet.WordConcatenatedComponentRow[] wordConcatenatedComponents
				= this.Current__WordConcatenated.GetWordConcatenatedComponentRows();
			
			SortedDictionary<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePairs
				= new SortedDictionary<short, BabebiDataSet.WordConcatenatedComponentRow>();

			foreach
			(
				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent
				in
				wordConcatenatedComponents
			)
			{
				keyValuePairs.Add(Convert.ToInt16(- wordConcatenatedComponent.Rank), wordConcatenatedComponent);
			}

			bool found = false;
			BabebiDataSet.WordConcatenatedComponentRow nextWordConcatenatedComponent = null;
			foreach
			(
				KeyValuePair<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePair in keyValuePairs
			)
			{
				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent = keyValuePair.Value;

				if (!found && wordConcatenatedComponent.Rank == selectedRank)
				{
					found = true;
				}
				else if(found && nextWordConcatenatedComponent == null)
				{
					nextWordConcatenatedComponent = wordConcatenatedComponent;
					break;
				}
			}
			if (nextWordConcatenatedComponent == null)
			{
				return;  /// c'était le dernier élément...
			}

			this.DataSet.EnforceConstraints = false;

			int position = 0;
			short newRank = Convert.ToInt16(keyValuePairs.Count + 1);
			foreach
			(
				KeyValuePair<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePair in keyValuePairs
			)
			{ 
				newRank--;

				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent = keyValuePair.Value;

				if (wordConcatenatedComponent == this.Current__WordConcatenatedComponent)
				{
					wordConcatenatedComponent.Rank = Convert.ToInt16(newRank - 1);

					position = wordConcatenatedComponent.Rank - 1;
				}
				else if (wordConcatenatedComponent == nextWordConcatenatedComponent)
				{
					wordConcatenatedComponent.Rank = Convert.ToInt16(newRank + 1);
				}
				else
				{ 
					wordConcatenatedComponent.Rank = Convert.ToInt16(newRank);
				}
			}

			this.DataSet.EnforceConstraints = true;

			this.guiTable__WordConcatenatedComponent.Populate();

			this.Compute__ConcatenatedString();

			this.BindingSource__WordConcatenatedComponent.CurrencyManager.Position = position;

			this.dataGridView__WordConcatenatedComponent.CurrentCell 
				= this.dataGridView__WordConcatenatedComponent.Rows[position].Cells[0];
		}

		private void button__WordConcatenate__Down_Click(object sender, EventArgs e)
		{
			if (this.Current__WordConcatenatedComponent == null)
			{
				return;
			}

			short selectedRank = this.Current__WordConcatenatedComponent.Rank;

			BabebiDataSet.WordConcatenatedComponentRow[] wordConcatenatedComponents
				= this.Current__WordConcatenated.GetWordConcatenatedComponentRows();
			
			SortedDictionary<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePairs
				= new SortedDictionary<short, BabebiDataSet.WordConcatenatedComponentRow>();

			foreach
			(
				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent
				in
				wordConcatenatedComponents
			)
			{
				keyValuePairs.Add(wordConcatenatedComponent.Rank, wordConcatenatedComponent);
			}

			bool found = false;
			BabebiDataSet.WordConcatenatedComponentRow nextWordConcatenatedComponent = null;
			foreach
			(
				KeyValuePair<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePair in keyValuePairs
			)
			{
				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent = keyValuePair.Value;

				if (!found && wordConcatenatedComponent.Rank == selectedRank)
				{
					found = true;
				}
				else if(found && nextWordConcatenatedComponent == null)
				{
					nextWordConcatenatedComponent = wordConcatenatedComponent;
					break;
				}
			}
			if (nextWordConcatenatedComponent == null)
			{
				return;  /// c'était le dernier élément...
			}

			this.DataSet.EnforceConstraints = false;

			int		position	= 0; 
			short	newRank		= 0;
			foreach
			(
				KeyValuePair<short, BabebiDataSet.WordConcatenatedComponentRow> keyValuePair in keyValuePairs
			)
			{ 
				newRank++;

				BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent = keyValuePair.Value;

				if (wordConcatenatedComponent == this.Current__WordConcatenatedComponent)
				{
					wordConcatenatedComponent.Rank = Convert.ToInt16(newRank + 1);

					position = wordConcatenatedComponent.Rank - 1;
				}
				else if (wordConcatenatedComponent == nextWordConcatenatedComponent)
				{
					wordConcatenatedComponent.Rank = Convert.ToInt16(newRank - 1);
				}
				else
				{ 
					wordConcatenatedComponent.Rank = newRank;
				}
			}

			this.DataSet.EnforceConstraints = true;

			this.guiTable__WordConcatenatedComponent.Populate();

			this.Compute__ConcatenatedString();

			this.BindingSource__WordConcatenatedComponent.CurrencyManager.Position = position;

			this.dataGridView__WordConcatenatedComponent.CurrentCell 
				= this.dataGridView__WordConcatenatedComponent.Rows[position].Cells[0];
		}



		private void button__WordConcatenatedComponent__Focus_Click(object sender, EventArgs e)
		{
			if (this.Current__WordConcatenatedComponent == null)
			{
				return;
			}

			this.Current__Word						= this.Current__WordConcatenatedComponent.WordRow;
			this.Current__WordOrPattern__of__Word	= this.Current__Word.WordOrPatternRowParent;
			this.Current__Word_Language				= (BabebiDataSet.Word_LanguageRow)(this.DataRow__Language(this.Current__Word));

			this.populate__Word();
		}

		private void button__WordConcatenated__CreateUpdate__Click()
		{
			if (this.Current__WordConcatenated == null)
			{
				return;
			}

			SortedDictionary<short, string> ranks__subStrings = new SortedDictionary<short, string>();
			foreach (BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent in this.Current__WordConcatenated.GetWordConcatenatedComponentRows())
			{
				string subString = wordConcatenatedComponent.WordRow.UniqueKeyString;

				int index = 0;
				if ( ! wordConcatenatedComponent.IsSubStringIndexNull())
				{
					index = wordConcatenatedComponent.SubStringIndex;
				}

				int length = subString.Length;
				if ( ! wordConcatenatedComponent.IsSubStringLengthNull())
				{
					length = wordConcatenatedComponent.SubStringLength;
				}

				subString = subString.Substring(index, length);

				ranks__subStrings.Add(wordConcatenatedComponent.Rank, subString);
			}

			string wordString = "";
			foreach (string subString in ranks__subStrings.Values)
			{
				wordString += subString;
			}

			Word.SetUniqueKeyString(this.Current__Word, wordString);
		///	this.Current__Word.UniqueKeyString = wordString;

			this.textBox__Word__String.Text = this.Current__Word.UniqueKeyString;
		}
		private void button__WordConcatenated__CreateUpdate__Click(object sender, EventArgs e)
		{
			this.button__WordConcatenated__CreateUpdate__Click();
		}

		private void bindingSource__WordConcatenatedComponent__CurrentChanged(object sender, EventArgs e)
		{
			if (this.BindingSource__WordConcatenatedComponent.Current != null && this.Current__WordConcatenated != null)
			{
				DataRow guiDataRow
					=
					(
						(DataRowView)
						(this.BindingSource__WordConcatenatedComponent.Current)
					).Row;

				int wordConcetenatedId = this.Current__WordConcatenated.Id;

				short rank = this.guiTable__WordConcatenatedComponent.GetValue__Rank(guiDataRow);

				this.Current__WordConcatenatedComponent
					= this.DataSet.WordConcatenatedComponent
					.FindByWordConcatenatedIdRank
					(wordConcetenatedId, rank);

				this.Current__Word__of__WordConcatenatedComponent
					= this.Current__WordConcatenatedComponent.WordRow;

				this.Current__Word_Language__of__WordConcatenatedComponent
					= this.DataSet.Word_Language
					.FindByWordIdLanguageCode
					(
						this.Current__Word__of__WordConcatenatedComponent.Id,
						this.Current__Language.Code
					);
			}
			else
			{
				this.Current__WordConcatenatedComponent						= null;
				this.Current__Word__of__WordConcatenatedComponent			= null;
				this.Current__Word_Language__of__WordConcatenatedComponent	= null;
			}
		}

		private void bindingSource__WordConcatenating__CurrentChanged(object sender, EventArgs e)
		{
			if (this.BindingSource__WordConcatenating.Current != null)
			{
				DataRow guiDataRow
					= 
					(
						(DataRowView)
						(this.BindingSource__WordConcatenating.Current)
					).Row;

				int		wordConcatenatedId	= this.guiTable__WordConcatenating.GetValue__WordConcatenatedId	(guiDataRow);
				short	rank				= this.guiTable__WordConcatenating.GetValue__Rank				(guiDataRow);

				this.Current__WordConcatenating = this.DataSet.WordConcatenatedComponent.FindByWordConcatenatedIdRank(wordConcatenatedId, rank);
			}
		}
	}
}