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
	{
		#region		populate & remove

		private void remove__WordFromPattern()
		{
			/// tactique : on va supprimer la 11P row FromPattern pour que cela cascade sur... tout :
			///    - PatternFromPattern,
			///    - les rows-enfants FromPatternLetters.

			this.DataSet.FromPattern.RemoveFromPatternRow(this.Current__FromPattern__of__WordFromPattern);

			this.Current__Word.ModeCode = MainForm.ModeCode_NotDefined;

			this.populate__WordFromPattern(PopulatingType.Cleaning);
		}

		/// <summary>
		/// Quels sont les cas qui se présentent ?
		/// 
		/// 1) au démarrage, on vient chercher à faire focus sur le dernier Word :
		///    - soit on le trouve pas => tout doit être vide.
		///    - soit on le trouve => on doit l'afficher avec le bon mode, si mode il y a.
		///    
		/// 2) lorsque l'on fait un Find : on devrait être dans une situation analogue à la précédente avec la 
		///    particularité que si le Found n'a pas de mode, alors il ne faut pas se trouvait dans la situation
		///    où on verrait le mode du previuously focused.
		/// 
		/// 3) lorsque l'on fait un CREATE de la base, la mode-extention doit être invisible (surtout que l'on a peut être fait un clone
		///    et que par defaut on a toujours, moisi-caché, les Current_#s de mode et les fields values du word de même type prcédent!!!).
		/// 
		/// 4) lorsque l'on fait un UPDATE du mode, la mode-extention doit être visible, forcement c'est toujours la même
		///    car il y en avait une avant et que l'on n'a pas pu la détruire.
		/// 
		/// 5) lorsque l'on crée une mode-extension à une base qui n'en avait pas, il faut l'afficher mais les Current_#s existent déjà.
		/// 
		/// 6) lorsqu'on focuse un Word avec son extension et que l'on veut change de type (de mode).
		/// 
		/// Case 1 (Load) :
		/// 
		/// Case 1a) :		(= on n'est donc pas specifiquement dans le cas WFP...)
		/// - les currents W et W_L sont nulles.
		/// - Il faut setter la combo-Type sur ND => tout est vide.
		/// 
		/// Case 1bA) :		(= on a un Current W ey W_L MAIS son mode est "" = on n'est donc pas specifiquement dans le cas WFP...)
		/// - les currents W et W_L sont founded.
		/// - Il faut setter la combo-Type sur ND => tout est vide.
		/// 
		/// Case 1bB) :		(= on a un Current W ey W_L ET son mode est "P" = on EST donc specifiquement dans le cas WFP. Enfin...)
		/// - les currents W et W_L sont founded.
		/// - Il faut setter la combo-Type sur FP => tout s'affiche.
		/// 
		/// Case 2 (FIND) = Case 1
		/// 
		/// Case 3 (CREATE (cloning ?) de la base) : 
		/// - il faut sété la combo-Type sur ND ET je me demande s'il ne faudrait pas appeler populate_W(de tous les modes) pour bien annihiler
		///   tous les Current_#(modes) moisis et cleaner les TBs, même si on ne les voit pas ?
		/// 
		/// case 4 (UPDATE du - hors combo-type -) : 
		/// - la forme de Create/UPDATE a DEJA sété TOUS les Current_#s et il n'y a que les textBoxes à remplir forcèment.
		/// 
		/// Case 5 (CREATE du mode FP) : 
		/// - la forme de CREATE/Update a DEJA sété TOUS les Current_#s et il n'y a que les textBoxes à remplir forcèment.
		/// 
		/// Case 6 (mode switch) :
		/// 
		/// - le parti-pris est de dire que l'on ne tue pas desuite "l'ancien" mode-extension pour pouvoir faire Restore.
		///   ça va être chaud à definir. Mais on peut dire que : 
		///      1) l'on se lance dans un CREATE d'un nouveau mode
		///      2) si ça réussit, juste avant de créer le nouveau mode on regarde spécifiquement qu'elle était l'ancien mode pour
		///			appeler le populate__DE_CE_MODE(...) en ayant changer le mode code juste avant pour cette methode dézingue les 
		///			current_#s-Mode et nettoie les fields-Mode zombies.
		/// 
		/// Je n'ai pas non plus envie de faire des FindBy...(...) en sachant que cela va forcement donner null.
		/// 
		/// Les cases sont donc finalement :
		/// 1) les Current__#(Mode)s ont déjà été calculés (car non nulls) => il faut juste séter les fields. (sortie de create/update).
		/// 2) On a changé de mode qui n'est plus FP => mesure anti-zombie : il faut nullifier les Current__#(Mode)s et cleaner les fields.
		/// 3) on sort du néant avec juste Curr__W et Curr__W_L de setter et on sait qu'on a le mode FP => faire les Finds et séter les fields.
		/// 
		/// => enum {Cleaning, FindingRowsAndSettingFields, SettingFieldsOnly }
		/// 
		/// Décision : on va donc rajouter un enum PopulatingType en argument de populate__WordFromPattern(...) :
		///		* cas 1 : populate__Word() --> event combo-type ND (=> Cleaning) or FP (=> FindingRowsAndSettingFields),
		///		* cas 2 : c'est le cas 1,
		///		* cas 3 : populate__Word() --> event combo-type sur ND (=> Cleaning) : pour bien éradiquer les zombies du Word précédent en cas de clonage.
		///		* cas 4 : button FP_CreateUpdate --> SettingFieldsOnly
		///		* cas 5 : button FP_CreateUpdate --> (=> Cleaning) sur l'ancien mode pour le dézinguer, puis SettingFieldsOnly sur le nouveau FP.
		///		* cas 6 : c'est le cas 5.
		/// 
		/// Est appelé par :
		/// - l'event selectdItem de combo-type.
		/// - en fin du bouton CreateUpdate du mode FP.
		/// - button Prior et Next
		/// 
		/// </summary>
		internal void populate__WordFromPattern(PopulatingType populatingType)
		{
			/// les Current__#(FromPattern) rows.
			if (populatingType == PopulatingType.Cleaning)
			{
				this.Current__WordFromPattern								= null;
				this.Current__FromPattern__of__WordFromPattern				= null;

				this.Current__Pattern__of__WordFromPattern__Parent			= null;
				this.Current__Pattern_Language__of__WordFromPattern__Parent = null;
			}
			else if (populatingType == PopulatingType.FindingRowsAndSettingFields)
			{
				this.Current__WordFromPattern								= this.DataSet.WordFromPattern.FindById(this.Current__Word.Id);
				this.Current__FromPattern__of__WordFromPattern					= this.Current__WordFromPattern.FromPatternRowParent;

				this.Current__Pattern__of__WordFromPattern__Parent				= this.Current__FromPattern__of__WordFromPattern.PatternRow;
				this.Current__Pattern_Language__of__WordFromPattern__Parent	= this.DataSet.Pattern_Language.FindByPatternIdLanguageCode(this.Current__Pattern__of__WordFromPattern__Parent.Id,	this.Current__Language.Code);
			}

			/// les textBoxes.
			if (populatingType == PopulatingType.Cleaning)
			{
				this.textBox__WordFromPattern__Pattern__UniqueKeyString		.Text	= null;
				this.textBox__WordFromPattern__Pattern__Id					.Text	= null;
				this.textBox__WordFromPattern__Pattern_Language__Meaning	.Text	= null;

				this.textBox__WordFromPattern__GuiHorizontalShift	.Text	= null;

				this.bindingSource__FromPatternLetter__of__Word.Filter = "FromPatternSubscriberCode = ''"; /// to have no row.

				this.button__WordFromPattern__CreateUpdate.Text = "CREATE";
			}
			else
			{
				this.textBox__WordFromPattern__Pattern__UniqueKeyString.Text	= this.Current__Pattern__of__WordFromPattern__Parent.UniqueKeyString;
				this.textBox__WordFromPattern__Pattern__Id.Text					= this.Current__Pattern__of__WordFromPattern__Parent.Id.ToString();
				this.textBox__WordFromPattern__Pattern_Language__Meaning.Text	= this.Current__Pattern_Language__of__WordFromPattern__Parent.Meaning;

				this.textBox__WordFromPattern__GuiHorizontalShift.Text			= this.Current__FromPattern__of__WordFromPattern.GuiHorizontalShift.ToString();

				this.bindingSource__FromPatternLetter__of__Word.Filter
					= "FromPatternSubscriberCode = '"
					+ this.Current__FromPattern__of__WordFromPattern.SubscriberCode
					+ "' AND FromPatternSubscriberId = '"
					+ this.Current__FromPattern__of__WordFromPattern.SubscriberId
					+ "'";

				this.button__WordFromPattern__CreateUpdate.Text = "UPDATE";
			}
		}

		#endregion	populate & remove
		#region		button events

		private void button__WordFromPattern__CreateUpdate__Click()
		{
			Form__WordFromPattern__CreateUpdate form = new Form__WordFromPattern__CreateUpdate(this);

			if (form.ShowDialog() == DialogResult.Cancel)
			{
				this.populate__Word();

				return;
			}
		}
		private void button__WordFromPattern__CreateUpdate__Click(object sender, EventArgs e)
		{
			this.button__WordFromPattern__CreateUpdate__Click();
		}

		private void button__WordFromPattern__FocusParentPattern__Click(object sender, EventArgs e)
		{
			this.Current__Pattern = this.Current__WordFromPattern.FromPatternRowParent.PatternRow;

			this.Current__Pattern_Language 
				= 
				this.DataSet.Pattern_Language
				.FindByPatternIdLanguageCode
				(
					this.Current__Pattern.Id,
					this.Current__Language.Code
				);

			this.populate__Pattern();

			this.tabControl__Main.SelectedTab = this.tabPage__Pattern;
		}

		private List<int> button__Word__FromPattern__PriorNext_Click(out int number_of_words, ref Dictionary<int, BabebiDataSet.WordRow> wordIds__words)
		{
			BabebiDataSet.FromPatternRow[] fromPatterns
				=
				(BabebiDataSet.FromPatternRow[])
				(
					this.Current__Pattern__of__WordFromPattern__Parent
					.GetFromPatternRows()
				);

			Dictionary<List<string>, int> letterLists__WordIds = new Dictionary<List<string>, int>();

			wordIds__words = new Dictionary<int, BabebiDataSet.WordRow>();
			
			number_of_words = 0;

			foreach (BabebiDataSet.FromPatternRow fromPattern in fromPatterns)
			{
				BabebiDataSet.WordRow word;
				if (fromPattern.SubscriberCode == MainForm.SubscriberCode_Word)
				{
					number_of_words++;

					word = this.DataSet.Word.FindById(fromPattern.SubscriberId);
				}
				else if (fromPattern.SubscriberCode == MainForm.SubscriberCode_Pattern)
				{
					continue;
				}
				else
				{
					throw new Exception(fromPattern.SubscriberCode);
				}

				BabebiDataSet.FromPatternLetterRow[] fromPatternLetters
					= fromPattern.GetFromPatternLetterRows();

				List<string> letterList = new List<string>();
				foreach (BabebiDataSet.FromPatternLetterRow fromPatternLetter in fromPatternLetters)
				{
					letterList.Add(fromPatternLetter.LetterString);
				}
				letterLists__WordIds	.Add(letterList, word.Id);
				wordIds__words	.Add(word.Id, word);
			}

			return this.getSortedListKeyedByLetterList(letterLists__WordIds);			
		}
		private void button__WordFromPattern__PriorSibling__Click(object sender, EventArgs e)
		{
			Dictionary<int, BabebiDataSet.WordRow> wordIds__words = new Dictionary<int, BabebiDataSet.WordRow>();

			List<int> sortedWordIds = this.button__Word__FromPattern__PriorNext_Click(out int number_of_words, ref wordIds__words);

			BabebiDataSet.WordRow priorWord = null;
			foreach (int wordId in sortedWordIds)
			{
				if (wordId != this.Current__Word.Id)
				{
					priorWord = wordIds__words[wordId];
				}
				else 
				{
					break;
				}
			}
			if (priorWord == null)
			{ 
				priorWord = wordIds__words[sortedWordIds[number_of_words - 1]]; /// si Current premier, alors Next dernier.
			}

			this.Current__Word			= priorWord;

			this.Current__Word_Language	
				= this.DataSet.Word_Language.FindByWordIdLanguageCode(this.Current__Word.Id, this.Current__Language.Code);
			
			this.Current__WordOrPattern__of__Word = this.Current__Word.WordOrPatternRowParent;

			this.populate__Word();
		}
		private void button__WordFromPattern__NextSibling__Click(object sender, EventArgs e)
		{
			Dictionary<int, BabebiDataSet.WordRow> wordIds__words = new Dictionary<int, BabebiDataSet.WordRow>();

			List<int> sortedWordIds = this.button__Word__FromPattern__PriorNext_Click(out int number_of_words, ref wordIds__words);

			bool foundCurrent = false;
			BabebiDataSet.WordRow nextWord = null;
			foreach (int wordId in sortedWordIds)
			{
				if (!foundCurrent && wordId == this.Current__Word.Id)
				{
					foundCurrent = true;
				}
				else if (foundCurrent)
				{
					nextWord = wordIds__words[wordId];

					break;
				}
			}
			if (nextWord == null)
			{ 
				nextWord = wordIds__words[sortedWordIds[0]]; /// si Current dernier, alors Next premier.
			}

			this.Current__Word = nextWord;
			
			this.Current__Word_Language 
				= this.DataSet.Word_Language
				.FindByWordIdLanguageCode
				(
					this.Current__Word.Id,
					this.Current__Language.Code
				);
						
			this.Current__WordOrPattern__of__Word = this.Current__Word.WordOrPatternRowParent;

			this.populate__Word();

		}

		#endregion	button events
	}
}