using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace Babebi4
{
	internal abstract class GuiTable__Word_Pattern : DataTable
	{
		protected MainForm	mainForm;
		protected bool		trueForWord__falseForPattern;
		protected string	modeCode;

		protected BabebiDataSet dataSet;

		#region		shortcuts

		protected BabebiDataSet.LanguageRow currentLanguage
		{
			get
			{
				return this.mainForm.Current__Language;
			}
		}
		protected string currentLanguageCode
		{
			get
			{
				return this.mainForm.Current__Language.Code;
			}
		}

		protected string dataTableName
		{
			get
			{
				if (trueForWord__falseForPattern)
				{
					return MainForm.SubscriberName_Word;
				}
				else
				{
					return MainForm.SubscriberName_Pattern;
				}
			}
		}
		protected string relationName__tableName_Language__tableName
		{
			get
			{
				return this.dataTableName + "_Language__" + this.dataTableName;
			}
		}
		protected DataTable dataTable
		{
			get
			{
				if (trueForWord__falseForPattern)
				{
					return this.dataSet.Word;
				}
				else
				{
					return this.dataSet.Pattern;
				}
			}
		}
		protected DataTable dataTable_Language
		{
			get
			{
				if (trueForWord__falseForPattern)
				{
					return this.dataSet.Word_Language;
				}
				else
				{
					return this.dataSet.Pattern_Language;
				}
			}
		}

		#endregion	shortcuts
		#region		table defining

		internal DataSet DataSet__for__MainForm__BindingSource;

		#region		Columns

		protected DataColumn column__Id;
		protected DataColumn column__UniqueKeyString;
		protected DataColumn column__Meaning;

		#endregion	Columns

		#endregion	table defining

		#region		getters : GetValue__[columnName](guiDataRow)

		internal int	GetValue__Id				(DataRow guiDataRow) { return guiDataRow.Field<int>(this.column__Id); }
		internal string GetValue__UniqueKeyString	(DataRow guiDataRow) { return guiDataRow.Field<string>(this.column__UniqueKeyString); }
		internal string GetValue__Meaning			(DataRow guiDataRow) { return guiDataRow.Field<string>(this.column__Meaning); }

		#endregion	getters : GetValue__[columnName](guiDataRow)

		#region		ctor

		internal GuiTable__Word_Pattern
		(
			MainForm mainform,
			bool trueForWord__falseForPattern,
			string modeCode
		)
		: base((trueForWord__falseForPattern ? "Word" : "Pattern") + "_")
		{
			this.mainForm = mainform;
			this.trueForWord__falseForPattern = trueForWord__falseForPattern;
			this.modeCode = modeCode;

			this.dataSet = this.mainForm.DataSet;

			#region		build the table

			this.DataSet__for__MainForm__BindingSource = new DataSet("DATASET_");

			this.DataSet__for__MainForm__BindingSource.Tables.Add(this);

			this.column__Id = this.Columns.Add("Id", typeof(int));
			this.column__UniqueKeyString = this.Columns.Add("UniqueKeyString", typeof(string));
			this.column__Meaning = this.Columns.Add("Meaning", typeof(string));

			this.column__Id.AllowDBNull = false;
			this.column__UniqueKeyString.AllowDBNull = false;
			this.column__Meaning.AllowDBNull = false;

			this.column__UniqueKeyString.MaxLength = 32;
			this.column__Meaning.MaxLength = 256;

			this.PrimaryKey = new DataColumn[] { this.column__Id };

			#endregion	build the table
			#region		subscribe to dataTable and dataTable_Language RowChanged events

			this.dataTable.RowChanging	+= DataTable__RowChanging;	/// spécialisé dans le changement d'Id.
			this.dataTable.RowChanged	+= DataTable__RowChanged;

			this.dataTable_Language.RowChanged += DataTable_Language__RowChanged;

			this.dataTable.RowDeleting += DataTable_RowDeleting;

			#endregion	subscribe to dataTable and dataTable_Language RowChanged events
		}

		#endregion	ctor
		#region		MainForm DataSet Column Value getters

		protected int		get__DataRow__Id(DataRow dataRow) { return dataRow.Field<int>("Id"); }
		protected string	get__DataRow__UniqueKeyString(DataRow dataRow) { return dataRow.Field<string>("UniqueKeyString"); }
		protected string	get__DataRow__ModeCode(DataRow dataRow) { return dataRow.Field<string>("ModeCode"); }

		protected int		get__DataRow_Language__Id			(DataRow dataRow_Language) { return dataRow_Language.Field<int		>(this.dataTableName + "Id"); }
		protected string	get__DataRow_Language__LanguageCode	(DataRow dataRow_Language) { return dataRow_Language.Field<string	>("LanguageCode"); }
		protected string	get__DataRow_Language__Meaning		(DataRow dataRow_Language) { return dataRow_Language.Field<string	>("Meaning"); }

		#endregion	MainForm DataSet Column Value getters
		#region		DataSet events listening

		protected DataRow guiDataRow(DataRow dataRow, out int dataRow__Id)
		{
			#region		where the out-of-scope rows are return-trapped.

			string dataRow__ModeCode = this.get__DataRow__ModeCode(dataRow);

			if (dataRow__ModeCode != this.modeCode)
			{
				dataRow__Id = -2;

				return null;
			}

			dataRow__Id = this.get__DataRow__Id(dataRow);

			bool isRelevantDataRow = this.isParentTheCurrent(dataRow__Id);
			if (!isRelevantDataRow)
			{
				return null;
			}

			#endregion	where the out-of-scope rows are return-trapped.

			DataRow guiDataRow = this.Find(dataRow__Id);

			return guiDataRow;
		}

		private void DataTable__RowChanged(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Change)
			{
				#region		(prior version)
				/*
				DataRow dataRow = e.Row;

				#region		where the out-of-scope rows are return-trapped.

				string dataRow__ModeCode = this.get__DataRow__ModeCode(dataRow);

				if (dataRow__ModeCode != this.modeCode)
				{
					return;
				}

				int dataRow__Id = this.get__DataRow__Id(dataRow);

				bool isRelevantDataRow = this.isParentTheCurrent(dataRow__Id);
				if (isRelevantDataRow)
				{
					return;
				}

				#endregion	where the out-of-scope rows are return-trapped.
				*/
				#endregion	(prior version)

				DataRow dataRow = e.Row;

				DataRow guiDataRow = this.guiDataRow(dataRow, out int dataRow__Id);     //	this.findGuiDataRow(dataRow__Id);

				if (guiDataRow != null)
				{
					/// Id
					int guiDataRow__Id = this.GetValue__Id(guiDataRow);
					if (guiDataRow__Id != dataRow__Id)
					{
						guiDataRow[this.column__Id] = dataRow__Id;
					}

					/// UKS
					string dataRow__UniqueKeyString = this.get__DataRow__UniqueKeyString(dataRow);
					string guiDataRow__UniqueKeyString = this.GetValue__UniqueKeyString(guiDataRow);
					if (guiDataRow__UniqueKeyString != dataRow__UniqueKeyString)
					{
						guiDataRow[this.column__UniqueKeyString] = dataRow__UniqueKeyString;
					}
				}
			}
		}

		private void DataTable__RowChanging(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Change)
			{
				if (this.Rows.Count == 0)	/// on commence par trop ambitieux : this.mainForm.Current__WordConcatenated == null || 
				{
					return;
				}

				DataRow dataRow = e.Row;
		

				int current__Id		= (int)(dataRow["Id", DataRowVersion.Current	]);	/// prior
				int proposed__Id	= (int)(dataRow["Id", DataRowVersion.Proposed	]); /// new

				if (proposed__Id != current__Id)
				{
					DataRow guiDataRow = this.Find(current__Id);

					if (guiDataRow != null)
					{
						guiDataRow[this.column__Id] = proposed__Id;

						guiDataRow.AcceptChanges();
					}
					
				}
			}
		}

		private void DataTable_Language__RowChanged(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Change)
			{
				DataRow dataRow_language = e.Row;

				#region		where the out-of-scope rows are return-trapped.

				string dataRow_Language__LanguageCode = this.get__DataRow_Language__LanguageCode(dataRow_language);
				if (dataRow_Language__LanguageCode != this.currentLanguageCode)
				{
					return;
				}

				int dataRow_Language__Id = this.get__DataRow_Language__Id(dataRow_language);

				DataRow dataRow = dataRow_language.GetParentRow(this.relationName__tableName_Language__tableName);
				if (dataRow == null)
				{
					return;
				}

				string dataRow__ModeCode = this.get__DataRow__ModeCode(dataRow);
				if (dataRow__ModeCode != this.modeCode)
				{
					return;
				}

				bool isRelevantDataRow = this.isParentTheCurrent(dataRow_Language__Id);
				if (!isRelevantDataRow)
				{
					return;
				}

				#endregion	where the out-of-scope rows are return-trapped.

				DataRow guiDataRow = this.Find(dataRow_Language__Id);

				if (guiDataRow != null)
				{
					string dataRow_Language__Meaning = this.get__DataRow_Language__Meaning(dataRow_language);
					string guiDataRow_Language__Meaning = this.GetValue__Meaning(guiDataRow);
					if (guiDataRow_Language__Meaning != dataRow_Language__Meaning)
					{
						guiDataRow[this.column__Meaning] = dataRow_Language__Meaning;
					}
				}
			}
		}

		private void DataTable_RowDeleting(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Delete)
			{
				DataRow dataRow = e.Row;

				int dataRow__Id = this.get__DataRow__Id(dataRow);

				DataRow guiDataRow = this.Find(dataRow__Id);

				if (guiDataRow != null)
				{
					this.Rows.Remove(guiDataRow);
				}
			}
		}

		#endregion	DataSet events listening

		internal	bool?	Populate()
		{
			this.Clear();

			if (this.currentLanguage == null)
			{
				return null;
			}

			bool has1RowAtLeast = false;
			foreach(List<object> valueList	in	this.getValueListArray())
			{
				this.addGuiDataRow(valueList);

				if (!has1RowAtLeast)
				{
					has1RowAtLeast = true;
				}
			}

			return has1RowAtLeast;
		}

		protected	DataRow addGuiDataRow(List<object> valueList)
		{
			return this.Rows.Add(valueList.ToArray());
		}

		internal	DataRow Find(int patternId)
		{
			return this.Rows.Find(patternId);
		}

		#region		virtual and abstract methods

		protected abstract bool isParentTheCurrent(int id);

		protected virtual List<object> guiDataRow_ValueList(DataRow dataRow)
		{
			List<object> valueList = new List<object>();

			int id = this.get__DataRow__Id(dataRow);
			valueList.Add(id);

			string uniqueKeyString = this.get__DataRow__UniqueKeyString(dataRow);
			valueList.Add(uniqueKeyString);

			DataRow dataRow_Language = this.dataTable_Language.Rows.Find(new object[] { id, this.currentLanguageCode });

			string meaning = this.get__DataRow_Language__Meaning(dataRow_Language);
			valueList.Add(meaning);

			return valueList;
		}

		protected abstract List<object>[] getValueListArray();

		#endregion	virtual and abstract methods
	}

	internal abstract class GuiTable__Word : GuiTable__Word_Pattern
	{
		internal DataColumn	WordType_LanguageName;
		
		internal string	GetValue__WordType_LanguageName(DataRow guiDataRow)			
		{
			return guiDataRow.Field<string>(this.WordType_LanguageName);
		}

		internal short get__DataRow__WordTypeId(DataRow dataRow)
		{
			return dataRow.Field<short>("WordTypeId");
		}

		internal GuiTable__Word
		(
			MainForm mainform, 
			string modeCode
		) 
		: base(mainform, true, modeCode)
		{
			this.WordType_LanguageName = this.Columns.Add("WordType_LanguageName", typeof(string));
			this.WordType_LanguageName.AllowDBNull = false;
			this.WordType_LanguageName.MaxLength = 256;

			this.dataTable.RowChanged += DataTable__RowChanged; 	
		}

		private string get__WordType_Language__Name(DataRow dataRow)
		{ 
			short dataRow__WordTypeId = this.get__DataRow__WordTypeId(dataRow);

			BabebiDataSet.WordType_LanguageRow wordType_language
				= this.dataSet.WordType_Language.FindByWordTypeIdLanguageCode
				(
					dataRow__WordTypeId,
					this.currentLanguageCode
				);

			return wordType_language.Name;
		}

		private void DataTable__RowChanged(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Change)
			{
				DataRow dataRow		= e.Row;

				DataRow guiDataRow	= this.guiDataRow(dataRow, out int dataRow__Id);

				if (guiDataRow != null)
				{
					string dataRow_Language__Meaning = this.get__WordType_Language__Name(dataRow);

					string guiDataRow__WordType_LanguageName = this.GetValue__WordType_LanguageName(guiDataRow);				

					if (guiDataRow__WordType_LanguageName != dataRow_Language__Meaning)
					{
						guiDataRow[this.WordType_LanguageName] = dataRow_Language__Meaning;
					}
				}
			}
		}

		protected override List<object> guiDataRow_ValueList(DataRow dataRow)
		{
			List<object> valueList = base.guiDataRow_ValueList(dataRow);

			string wordType_Language__Name = this.get__WordType_Language__Name(dataRow);
			valueList.Add(wordType_Language__Name);

			return valueList;
		}
	}



}
