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

namespace TelerikTestReal
{
	public class TestParEditorCollection
	{
		public List<TestParItem> Items = new List<TestParItem>();

		public BindingList<TestParEditorItem> EditorItems { get; } = new BindingList<TestParEditorItem>();

		private int maxGridId = 0;

		public TestParEditorCollection()
		{
			EditorItems.ListChanged += Items_ListChanged;
		}

		public void Add()
		{
			Add(new TestParItem());
		}

		public void Add(TestType testType)
		{
			Add(new TestParItem() { TestType = testType });
		}

		public void Add(TestParItem item)
		{
			Items.Add(item);

			var editorItem = new TestParEditorItem(item, ++maxGridId);
			EditorItems.Add(editorItem);

			if (item.HasSubItems)
				AttachSubItems(editorItem);

			RenumberRows();
		}

		public void Remove(TestParEditorItem editorItem)
		{
			DoRemove(editorItem);
			RenumberRows();
		}

		public void Remove(List<TestParEditorItem> editorItems)
		{
			foreach (var ed in editorItems)
				DoRemove(ed);

			RenumberRows();
		}

		public void MoveUp(List<TestParEditorItem> editorItems)
		{
			MoveUp(editorItems.Where(ed => ed.IsItem).Select(ed => ed.Item).ToList());
		}

		public void MoveUp(List<TestParItem> items)
		{
			foreach (var item in items)
			{
				int pos = Items.IndexOf(item);
				if (pos <= 0)
					return;

				var tmp = Items[pos - 1];
				Items[pos - 1] = item;
				Items[pos] = tmp;
			}

			DoRefreshEditorItems();
		}

		public void MoveDown(List<TestParEditorItem> editorItems)
		{
			MoveDown(editorItems.Where(ed => ed.IsItem).Select(ed => ed.Item).ToList());
		}

		public void MoveDown(List<TestParItem> items)
		{
			foreach (var item in items)
			{
				int pos = Items.IndexOf(item);
				if (pos < 0)
					return;

				var tmp = Items[pos + 1];
				Items[pos + 1] = item;
				Items[pos] = tmp;
			}

			DoRefreshEditorItems();
		}

		public void Clear()
		{
			Items.Clear();
			EditorItems.Clear();
			maxGridId = 0;
		}

		private void DoRefreshEditorItems()
		{
			EditorItems.Clear();
			maxGridId = 0;

			foreach (var item in Items)
			{
				var editorItem = new TestParEditorItem(item, ++maxGridId);
				EditorItems.Add(editorItem);

				if (item.HasSubItems)
					AttachSubItems(editorItem);
			}

			RenumberRows();
		}

		private void DoRemove(TestParEditorItem editorItem)
		{
			if (!editorItem.IsItem)
				return;
			if (!EditorItems.Contains(editorItem))
				return;

			Items.Remove(editorItem.Item);

			DetachSubItems(editorItem);
			EditorItems.Remove(editorItem);
		}

		private void AttachSubItems(TestParEditorItem editorItem)
		{
			if (editorItem.Item.SubItemsCount == 0)
				return;

			var names = GetSubItemNames(editorItem.Item.TestType);
			for (int i = 0; i < editorItem.Item.SubItemsCount; i++)
			{
				var subItem = editorItem.Item.SubItems[i];
				var name = (i < names.Length) ? names[i] : $"({i + 1})";
				var ed = new TestParEditorItem(subItem, ++maxGridId, editorItem.GridID, name);
				editorItem.SubItems.Add(ed);
				EditorItems.Add(ed);
			}
		}

		private void DetachSubItems(TestParEditorItem editorItem)
		{
			foreach (var ed in editorItem.SubItems)
				EditorItems.Remove(ed);
		}

		private void RenumberRows()
		{
			int nr = 1;
			foreach (var editorItem in EditorItems)
			{
				if (editorItem.IsSubItem)
					continue;

				editorItem.Code = $"P{nr}";
				int subnr = 1;
				foreach (var subitem in editorItem.SubItems)
					subitem.Code = $"P{nr}.{subnr++}";
				nr++;
			}
		}

		private string[] GetSubItemNames(TestType testType)
		{
			switch (testType)
			{
				case TestType.TestNitu:
					return new string[] { "Priemer", "Vyska", "Tvar", "Naklon" };
				case TestType.TestZatky:
					return new string[] { "Hlbka", "Naklon" };
				case TestType.TestKolika:
					return new string[] { "Vyska", "Priemer" };
				default:
					return null;
			}
		}

		private void Items_ListChanged(object sender, ListChangedEventArgs e)
		{
			if ((e.ListChangedType == ListChangedType.ItemChanged) && (e.PropertyDescriptor != null) && (e.PropertyDescriptor.Name == "TestType"))
			{
				HandleTestTypeChanged(EditorItems[e.NewIndex]);
				EditorItems.ResetBindings();
			}

			if (e.ListChangedType == ListChangedType.ItemAdded)
			{
				string subName = EditorItems[e.NewIndex].SubItemName;
				// OK, fired	
			}
		}

		private void HandleTestTypeChanged(TestParEditorItem editorItem)
		{
			DetachSubItems(editorItem);
			AttachSubItems(editorItem);
		}
	}
}
