using System;
using System.Collections;
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;
using System.Xml.Linq;

namespace ComponentLibrary1.tree_list
{
	public partial class TreeList : UserControl
	{
		private List<string> CategoriesNames = new List<string>();

		public TreeList()
		{
			InitializeComponent();
		}

		public void SetCategories (List<string> categories)
		{
			CategoriesNames = categories;
		}

		public void AddTreeListObject<T>(T treeListObject) where T : class, new()
		{
			if (CategoriesNames == null || CategoriesNames.Count == 0)
			{
				throw new Exception("CategoriesNames is null or empty");
			}
			if (treeListObject == null)
			{
				throw new ArgumentException("treeObject is null");
			}
			Queue<string> values = new Queue<string>();
			Type type = treeListObject.GetType();
			foreach (string categoryName in CategoriesNames)
			{
				string? value = type.GetProperty(categoryName)?.GetValue(treeListObject) as string;
				if (string.IsNullOrEmpty(value))
				{
					throw new ArgumentException($"{type.Name}.{categoryName} is not found or is not a not empty string");
				}
				values.Enqueue(value);
			}
			TreeNodeCollection nodeCollection = treeView.Nodes;
			string hierarchyElement = values.Dequeue();
			while (values.Count > 0)
			{
				bool branchIsFind = false;
				foreach (TreeNode node in nodeCollection)
				{
					if (node.Text == hierarchyElement)
					{
						branchIsFind = true;
						nodeCollection = node.Nodes;
						hierarchyElement = values.Dequeue();
						break;
					}
				}
				if (branchIsFind)
				{
					continue;
				}
				TreeNode newBranch = nodeCollection.Add(hierarchyElement);
				nodeCollection = newBranch.Nodes;
				hierarchyElement = values.Dequeue();
			}
			TreeNode newLeaf = nodeCollection.Add(hierarchyElement);
			for(TreeNode node = newLeaf; node != null; node = node.Parent)
			{
				node.Expand();
			}
		}

		public T? GetSelectedObject<T>() where T : class, new()
		{
			if(treeView.SelectedNode == null)
			{
				throw new Exception("There are no selected nodes");
			}
			T result = new T();
			Type type = typeof(T);
			int i;
			TreeNode treeNode = treeView.SelectedNode;
			for (i = CategoriesNames.Count - 1; i >= 0 && treeNode != null; i--, treeNode = treeNode.Parent)
			{
				type.GetProperty(CategoriesNames[i])?.SetValue(result, treeNode.Text);
			}
			if(treeNode != null || i >= 0)
			{
				return null;
			}
			return result;
		}

		public void Clear()
		{
			treeView.Nodes.Clear();
		}
	}
}