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__WordConcatenatedComponent__Create : Form
	{
		private MainForm mainForm;

		bool trueForCreate__falseForUpdate;

		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.WordConcatenatedDataTable				table__WordConcatenated				{ get { return this.mainForm.DataSet.WordConcatenated; } }
		private BabebiDataSet.WordConcatenatedComponentDataTable	table__WordConcatenatedComponent	{ get { return this.mainForm.DataSet.WordConcatenatedComponent; } }

		#region		guiTable__Word

		private DataSet			guiDataSet;

		private DataTable		guiTable__Word;
		private DataColumn		guiColumn__Word__Id;
		private DataColumn		guiColumn__Word__String;
		private DataColumn		guiColumn__Word__Meaning;

		private BindingSource	bindingSource__Word;

		#endregion	guiTable__Word

		private BabebiDataSet.WordRow						current__Word
		{
			get
			{
				return this.mainForm.Current__Word;
			}
		}
		private BabebiDataSet.WordConcatenatedRow			current__WordConcatenated
		{ 
			get 
			{ 
				return this.mainForm.Current__WordConcatenated; 
			}
		}
		private BabebiDataSet.WordConcatenatedComponentRow	current__WordConcatenatedComponent
		{ 
			get 
			{ 
				return this.mainForm.Current__WordConcatenatedComponent; 
			}
			set 
			{ 
				this.mainForm.Current__WordConcatenatedComponent = value; 
			}
		}
		private BabebiDataSet.WordRow						current__Word__of__WordConcatenatedComponent
		{ 
			get 
			{ 
				return this.mainForm.Current__Word__of__WordConcatenatedComponent; 
			}
			set 
			{ 
				this.mainForm.Current__Word__of__WordConcatenatedComponent = value; 
			}
		}
		private BabebiDataSet.Word_LanguageRow				current__Word_Language__of__WordConcatenatedComponent
		{ 
			get 
			{ 
				return this.mainForm.Current__Word_Language__of__WordConcatenatedComponent; 
			}
			set 
			{ 
				this.mainForm.Current__Word_Language__of__WordConcatenatedComponent = value; 
			}
		}

		private BabebiDataSet.LanguageRow					current__Language
		{
			get { return this.mainForm.Current__Language; }
		}
		private string	currentLanguageCode
		{
			get { return this.mainForm.Current__Language.Code; }
		}

		private BabebiDataSet.WordRow			selected__Word__of__WordConcatenatedComponent				= null;
		private BabebiDataSet.Word_LanguageRow	selected__Word_Language__of__WordConcatenatedComponent		= null;

		private SubStringInformation selectedSubStringInformation;

		#region		ctors

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

			this.trueForCreate__falseForUpdate = trueForCreate__falseForUpdate;

			#region		guiTable__Word

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

			this.guiTable__Word = this.guiDataSet.Tables.Add("Word_");

			this.guiColumn__Word__Id		= this.guiTable__Word.Columns.Add("Id"		, typeof(int));
			this.guiColumn__Word__String	= this.guiTable__Word.Columns.Add("String"	, typeof(string));
			this.guiColumn__Word__Meaning	= this.guiTable__Word.Columns.Add("Meaning"	, typeof(string));

			this.guiTable__Word.PrimaryKey = new DataColumn[] { this.guiColumn__Word__Id };

			this.bindingSource__Word = new BindingSource(this.guiDataSet, this.guiTable__Word.TableName);

			this.dataGridView_Word.DataSource = this.bindingSource__Word;

			this.bindingSource__Word.CurrentChanged += bindingSource__Word_CurrentChanged;

			#endregion	guiTable__Word

			if (this.trueForCreate__falseForUpdate)
			{
				SubStringInformation.Populate__Combo__Index(this.comboBox__SubStringIndex);
			}
			else
			{
				this.button__CreateUpdate.Text = "UPDATE";

				this.selected__Word__of__WordConcatenatedComponent			= this.current__Word__of__WordConcatenatedComponent;
				this.selected__Word_Language__of__WordConcatenatedComponent	= this.current__Word_Language__of__WordConcatenatedComponent;

				this.populate__SelectedWordInformation();

				WordConcatenated.Read_SubString_Index_and_Length_from_DataRow
				(
					this.current__WordConcatenatedComponent, 
				out int index, 
				out int length
				);

				this.selectedSubStringInformation = new SubStringInformation(index, length);
				
				this.comboBox__SubStringIndex	.SelectedItem = this.selectedSubStringInformation.IndexSelectedItem;
				/// event
				this.comboBox__SubStringLength	.SelectedItem = this.selectedSubStringInformation.LengthSelectedItem;
			}
		}

		public Form__WordConcatenatedComponent__Create()
		{
			InitializeComponent();
		}

		#endregion	ctors

		private void populate__SelectedWordInformation()
		{ 
			this.textBox__SelectedWordId		.Text = this.selected__Word__of__WordConcatenatedComponent.Id.ToString();
			this.textBox__SelectedWordString	.Text = this.selected__Word__of__WordConcatenatedComponent.UniqueKeyString;
			this.textBox__SelectedWordMeaning	.Text = this.selected__Word_Language__of__WordConcatenatedComponent.Meaning;

			SubStringInformation.Populate__Combo__Index
				(
					this.comboBox__SubStringIndex, 
					this.textBox__SelectedWordString.Text.Length
				);
		}

		private void populate__SelectedWordInformation(int wordId, bool findWord = true, bool findWord_Language = true)
		{
			this.selected__Word__of__WordConcatenatedComponent
				= this.table__Word
				.FindById(wordId);

			this.selected__Word_Language__of__WordConcatenatedComponent
				= this.table__Word_Language
				.FindByWordIdLanguageCode
				(
					wordId,
					this.currentLanguageCode
				);

			this.populate__SelectedWordInformation();
		}

		private void populate__SelectedWordInformation(DataRow guiWordDataRow)
		{
			int wordId = (int)(guiWordDataRow[this.guiColumn__Word__Id]);

			this.populate__SelectedWordInformation(wordId);
		}

		private bool doNotSearch = false;

		private void textBox__SearchedWordString_TextChanged(object sender, EventArgs e)
		{
			if (this.doNotSearch)
			{
				return;
			}

			string wordString = this.textBox__SearchedWordString.Text;

			this.guiTable__Word.Clear();

			if (wordString.Length < 2)
			{
				this.doNotSearch = true;
				this.textBox__SearchedWordMeaning.Text = null;
				this.doNotSearch = false;

				return;
			}
			else
			{
				DataRow[] selectedWords 
					= this.table__Word
					.Select
					(
						"UniqueKeyString LIKE '" + wordString + "*'" + 
						" AND " + 
						"NOT(UniqueKeyString = '" + this.current__Word.UniqueKeyString + "')"
					);

				if (selectedWords.Length == 1)
				{
					this.selected__Word__of__WordConcatenatedComponent = (BabebiDataSet.WordRow)(selectedWords[0]);

					this.populate__SelectedWordInformation
					(
						this.selected__Word__of__WordConcatenatedComponent.Id, 
						false, 
						true
					);

					this.doNotSearch = true;
					this.textBox__SearchedWordMeaning.Text = this.selected__Word_Language__of__WordConcatenatedComponent.Meaning;
					this.doNotSearch = false;
				}
				else
				{
					bool matching = false;

					foreach (BabebiDataSet.WordRow selectedWord in selectedWords)
					{
						BabebiDataSet.Word_LanguageRow selectedWord_Language
							= this.table__Word_Language
							.FindByWordIdLanguageCode
							(
								selectedWord.Id,
								this.currentLanguageCode
							);

						this.guiTable__Word
							.Rows
							.Add
							(
								selectedWord.Id,
								selectedWord.UniqueKeyString,
								selectedWord_Language.Meaning
							);

						if (!matching && selectedWord.UniqueKeyString == wordString)
						{
							matching = true;

							this.selected__Word__of__WordConcatenatedComponent			= selectedWord;
							this.selected__Word_Language__of__WordConcatenatedComponent	= selectedWord_Language;
						}
					}

					if (matching)
					{
						this.populate__SelectedWordInformation();
					}

					this.doNotSearch = true;
					this.textBox__SearchedWordMeaning.Text = null; 
					this.doNotSearch = false;
				}
			}
		}

		private void textBox__SearchedWordMeaning_TextChanged(object sender, EventArgs e)
		{
			if (this.doNotSearch)
			{
				return;
			}

			string word_language__meaning = this.textBox__SearchedWordMeaning.Text;

			this.guiTable__Word.Clear();

			if (word_language__meaning.Length < 2)
			{
				this.doNotSearch = true;
				this.textBox__SearchedWordString.Text = null;
				this.doNotSearch = false;

				return;
			}
			else
			{
				DataRow[] selectedWord_Languages 
					= this.table__Word_Language
					.Select
					(
						"LanguageCode = '" + this.mainForm.Current__Language.Code +	"'" +
						" AND " + 
						"Meaning LIKE '*" + word_language__meaning + "*'"
					);
				/// ici on n'arrive pas à exclure le 'base' Word comme dans le recherche précédente par UniqueKeyString.
				/// Faudrait rajouter l'expression WordUniqueKeyString dans W_L...
				 

				if (selectedWord_Languages.Length == 1)
				{
					this.selected__Word_Language__of__WordConcatenatedComponent	
						= 
						(BabebiDataSet.Word_LanguageRow)
						(selectedWord_Languages[0]);

					this.selected__Word__of__WordConcatenatedComponent 
						=  this.selected__Word_Language__of__WordConcatenatedComponent.WordRowParent;
					
					this.populate__SelectedWordInformation();

					this.doNotSearch = true;
					this.textBox__SearchedWordString.Text = null;
					this.doNotSearch = false;
				}
				else
				{
					bool matching = false;

					foreach (BabebiDataSet.Word_LanguageRow selectedWord_Language in selectedWord_Languages)
					{
						BabebiDataSet.WordRow selectedWord = selectedWord_Language.WordRowParent;

						this.guiTable__Word
							.Rows
							.Add
							(
								selectedWord			.Id,
								selectedWord			.UniqueKeyString,
								selectedWord_Language	.Meaning
							);

						if (! matching && selectedWord_Language.Meaning == word_language__meaning)
						{
							matching = true;

							this.selected__Word__of__WordConcatenatedComponent			= selectedWord;
							this.selected__Word_Language__of__WordConcatenatedComponent	= selectedWord_Language;
						}
					}

					if (matching)
					{
						this.populate__SelectedWordInformation();
					}

					this.doNotSearch = true;
					this.textBox__SearchedWordString.Text = null; 
					this.doNotSearch = false;
				}
			}
		}

		private void bindingSource__Word_CurrentChanged(object sender, EventArgs e)
		{
			if (this.dataGridView_Word.Focused)
			{
				this.populate__SelectedWordInformation(((DataRowView)(this.bindingSource__Word.Current)).Row);

				/// cleaning
				this.doNotSearch = true;
				this.textBox__SearchedWordString.Text	= null;
				this.textBox__SearchedWordMeaning.Text	= null;
				this.doNotSearch = false;
			}
		}

		private void comboBox__SubStringIndex_SelectedIndexChanged(object sender, EventArgs e)
		{
			SubStringInformation.Populate__Combo__Length
				(
					this.comboBox__SubStringLength, 
					this.textBox__SelectedWordString.Text.Length,
					(string)(this.comboBox__SubStringIndex.SelectedItem)
				);
		}

		private void comboBox__SubStringLength_SelectedIndexChanged(object sender, EventArgs e)
		{
			this.selectedSubStringInformation 
				= new SubStringInformation
				(
					(string)(this.comboBox__SubStringIndex.SelectedItem),
					(string)(this.comboBox__SubStringLength.SelectedItem)
				);

			this.compute__SubString();
		}

		internal static void WriteSubStringIndexAndLengthToDataRow
		(
			BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent, 
			SubStringInformation subStringInformation,
			bool setDBNull
		)
		{
			if(subStringInformation.Length != 0 ||	subStringInformation.Index != 0)
			{
				wordConcatenatedComponent.SubStringIndex
					= Convert.ToInt16(subStringInformation.Index);

				if (subStringInformation.Length != 0)
				{
					wordConcatenatedComponent.SubStringLength
						= Convert.ToInt16(subStringInformation.Length);
				}
				else
				{
					if (setDBNull)
					{
						wordConcatenatedComponent.SetSubStringLengthNull();
					}
				}
			}
			else
			{
				if (setDBNull)
				{
					wordConcatenatedComponent.SetSubStringIndexNull();
					wordConcatenatedComponent.SetSubStringLengthNull();
				}
			}
		}


		private void compute__SubString()
		{
			if (string.IsNullOrEmpty(this.textBox__SelectedWordString.Text))
			{
				this.textBox__SubString.Text = null;

				return;
			}

			this.textBox__SubString.Text 
				= WordConcatenated.Compute__SubString
				(
					this.textBox__SelectedWordString.Text,
					this.selectedSubStringInformation.Index,
					this.selectedSubStringInformation.Length
				);
		}

		private void button__Create__Click(object sender, EventArgs e)
		{
			if (this.selected__Word__of__WordConcatenatedComponent == null)
			{
				MessageBox.Show("A 'Word' must be selected.", "Missing Word", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}

			if (this.trueForCreate__falseForUpdate)
			{
				#region		about rank

				short rank = 0;
				foreach
				(
					BabebiDataSet.WordConcatenatedComponentRow wordConcatenatedComponent
					in
					this.current__WordConcatenated.GetWordConcatenatedComponentRows()
				)
				{
					if (wordConcatenatedComponent.Rank > rank)
					{
						rank = wordConcatenatedComponent.Rank;
					}
				}
				rank++;

				#endregion	about rank

				this.mainForm.Current__WordConcatenatedComponent = this.table__WordConcatenatedComponent.NewWordConcatenatedComponentRow();

				this.mainForm.Current__WordConcatenatedComponent.WordConcatenatedRow = this.mainForm.Current__WordConcatenated;
				this.mainForm.Current__WordConcatenatedComponent.Rank = rank;
				this.mainForm.Current__WordConcatenatedComponent.WordRow = this.selected__Word__of__WordConcatenatedComponent;

				WriteSubStringIndexAndLengthToDataRow(this.mainForm.Current__WordConcatenatedComponent, this.selectedSubStringInformation, false);


				this.table__WordConcatenatedComponent.AddWordConcatenatedComponentRow(this.mainForm.Current__WordConcatenatedComponent);
			}
			else
			{
				this.mainForm.Current__WordConcatenatedComponent.WordRow = this.selected__Word__of__WordConcatenatedComponent;

				WriteSubStringIndexAndLengthToDataRow(this.mainForm.Current__WordConcatenatedComponent, this.selectedSubStringInformation, true);
			}

			this.current__Word__of__WordConcatenatedComponent			= this.selected__Word__of__WordConcatenatedComponent;
			this.current__Word_Language__of__WordConcatenatedComponent	= this.selected__Word_Language__of__WordConcatenatedComponent;

			this.mainForm.Compute__ConcatenatedString();

			this.DialogResult = DialogResult.OK;

			this.Close();
		}
	}

	internal class SubStringInformation
	{
		
		/// Start from the 1st Letter
		/// 0123456789012345	
		/// (to-the-end)
		/// 1 character

		internal int Index;
		internal int Length;

		internal string IndexSelectedItem;
		internal string LengthSelectedItem;

		internal SubStringInformation(int index, int length)
		{
			this.Index = index;
			this.Length = length;

			if (this.Length == 0)
			{
				this.LengthSelectedItem = "To the end";
			}
			else if (this.Length == 1)
			{
				this.LengthSelectedItem = "1 character";
			}
			else if (this.Length >= 2 && this.Length <= 9)
			{
				this.LengthSelectedItem = this.Length.ToString() + " characters";
			}
			else
			{
				throw new Exception();
			}

			if (this.Index == 0)
			{
				this.IndexSelectedItem = "Start from the 1st Letter";
			}
			else
			{
				if (this.Index == 1)
				{
					this.IndexSelectedItem = "Start from the 2nd Letter";
				}
				else if (this.Index == 2)
				{
					this.IndexSelectedItem = "Start from the 3rd Letter";
				}
				else if (this.Index >= 3)
				{
					this.IndexSelectedItem = "Start from the " + (this.Index + 1).ToString()  + "th Letter";
				}
				else
				{
					throw new Exception();
				}
			}
		}

		internal SubStringInformation(string indexSelectedItem, string lengthSelectedItem)
		{
			this.IndexSelectedItem	= indexSelectedItem;
			this.LengthSelectedItem	= lengthSelectedItem;

			string	indexDigit = this.IndexSelectedItem.Substring(15, 1);
			this.Index = int.Parse(indexDigit) - 1;  /// due to 0-based.

			if (this.LengthSelectedItem == "To the end")
			{
				this.Length = 0;
			}
			else
			{ 
				string	lengthDigit = this.LengthSelectedItem.Substring(0, 1);

				this.Length = int.Parse(lengthDigit);
			}
		}

		/// <summary>
		/// état minimal par défaut.
		/// </summary>
		internal SubStringInformation()
		{
			this.Index	= 0;
			this.Length	= 0;

			this.IndexSelectedItem	= "Start from the 1st Letter";
			this.LengthSelectedItem	= "To the end";
		}


		internal static void Populate__Combo__Index	(ComboBox comboBox__SubStringIndex, int selectedWordLength)
		{ 
			comboBox__SubStringIndex.Items.Clear();

			for (int i = 0 ; i < selectedWordLength - 1 ; i++)
			{
						if (i == 0){ comboBox__SubStringIndex.Items.Add("Start from the 1st Letter"); }
				else	if (i == 1){ comboBox__SubStringIndex.Items.Add("Start from the 2nd Letter"); }
				else	if (i == 2){ comboBox__SubStringIndex.Items.Add("Start from the 3rd Letter"); }
				else
				{ 
					comboBox__SubStringIndex.Items.Add("Start from the " + (i + 1).ToString() + "th Letter"); 
				}
			}

			comboBox__SubStringIndex.SelectedItem = comboBox__SubStringIndex.Items[0];
		}
		internal static void Populate__Combo__Index	(ComboBox comboBox__SubStringIndex)
		{ 
			comboBox__SubStringIndex.Items.Clear();

			comboBox__SubStringIndex.Items.Add("Start from the 1st Letter");

			if (comboBox__SubStringIndex.Items.Count == 1)
			{ 
				comboBox__SubStringIndex.SelectedItem = comboBox__SubStringIndex.Items[0];
			}
		}

		internal static void Populate__Combo__Length(ComboBox comboBox__subStringLength, int selectedWordLength, string subStringIndexSelectedItem)
		{ 
			comboBox__subStringLength.Items.Clear();

			string	indexDigit	= subStringIndexSelectedItem.Substring(15, 1);
			int		index		= int.Parse(indexDigit) - 1;

			int remainingLength = selectedWordLength - index;

			comboBox__subStringLength.Items.Clear();

			for (int i = 0; i <= remainingLength; i++)
			{
						if (i == 0){ comboBox__subStringLength.Items.Add("To the end"); }
				else	if (i == 1){ comboBox__subStringLength.Items.Add("1 character"); }
				else
				{ 
					comboBox__subStringLength.Items.Add( i.ToString() + " characters");
				}
			}

			comboBox__subStringLength.SelectedItem = comboBox__subStringLength.Items[0];
		}
	}
}
