using ComponentLibrary1.office_package;
using ComponentLibrary1.office_package.HelperEnums;
using ComponentLibrary1.office_package.HelperModels;
using ComponentLibrary1.office_package.Implements;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComponentLibrary1.pdf_table
{
	public partial class PdfTable : Component
	{
		ISaveToPdf SaveToPdf = new SaveToPdf();

		public PdfTable()
		{
			InitializeComponent();
		}

		public PdfTable(IContainer container)
		{
			container.Add(this);

			InitializeComponent();
		}
		public void CreatePdf<T>(PdfTableInfo<T> info)
		{
			info.CheckFields();
			SaveToPdf.CreatePdf(info);
			SaveToPdf.CreateParagraph(new PdfParagraph
			{
				Text = info.Title,
				Style = "NormalTitle",
				ParagraphAlignment = PdfParagraphAlignmentType.Center
			});
			SaveToPdf.CreateTableWithColumns(info.Data.Count + 2);
			SaveToPdf.CreateRow(new PdfRowParameters());
			int rowIndex = 0;
			int columnIndex = 0;
			List<string> properties = new List<string>();
			string? header;
			foreach (var node in info.Headers)
			{
				if (string.IsNullOrWhiteSpace(node.Text))
				{
					throw new Exception("Cannot read header");
				}
				SaveToPdf.CreateRow(new PdfRowParameters());
				SaveToPdf.InsertTextIntoCell(
					rowIndex, 
					columnIndex, 
					new PdfCellParameters
					{
						Text = node.Text,
						Style = "NormalTitle",
						ParagraphAlignment = PdfParagraphAlignmentType.Center
					});
				if (node.Nodes.Count == 0)
				{
					SaveToPdf.MergeCells(new PdfCellsMergeParameters
					{
						RowIndex = rowIndex,
						ColumnIndex = columnIndex,
						Direction = PdfCellsMergeDirections.Right
					});
					header = node.Tag as string;
					if (header == null)
					{
						throw new Exception("Cannot read property name");
					}
					properties.Add(header);
					rowIndex++;
				}
				else
				{
					int mergeRowIndex = rowIndex;
					int mergeColumnIndex = columnIndex;
					foreach (TreeNode child in node.Nodes)
					{
						if (string.IsNullOrWhiteSpace(child.Text))
						{
							throw new Exception("Cannot read header");
						}
						SaveToPdf.CreateRow(new PdfRowParameters());
						SaveToPdf.InsertTextIntoCell(
							rowIndex,
							columnIndex + 1,
							new PdfCellParameters
							{
								Text = child.Text,
								Style = "NormalTitle",
								ParagraphAlignment = PdfParagraphAlignmentType.Left
							});
						header = child.Tag as string;
						if (header == null)
						{
							throw new Exception("Cannot read property name");
						}
						properties.Add(header);
						rowIndex++;
					}
					SaveToPdf.MergeCells(new PdfCellsMergeParameters
					{
						RowIndex = mergeRowIndex,
						ColumnIndex = mergeColumnIndex,
						Direction = PdfCellsMergeDirections.Down,
						CellNumber = node.Nodes.Count - 1
					});
				}
			}
			columnIndex = 2;
			foreach (var obj in info.Data)
			{
				if (obj == null)
				{ 
					throw new Exception("Table Data element cannot be null"); 
				}
				List<string> cells = new List<string>();
				for (int i = 0; i < properties.Count; i++)
				{
					string propertyName = properties[i];
					var property = obj.GetType().GetProperty(propertyName);
					if (property is null)
					{
						throw new ArgumentException($"Failed to find property {propertyName} in provided objects class");
					}
					var value = property.GetValue(obj)?.ToString();
					if (value == null)
					{
						throw new ArgumentException($"Failed to find property {propertyName} in provided objects class");
					}
					cells.Add(value);
				}
				SaveToPdf.InsertTextIntoColumn(new PdfColumnParameters
				{
					Texts = cells,
					ColumnIndex = columnIndex,
					Style = "Normal",
					ParagraphAlignment= PdfParagraphAlignmentType.Left
				});
				columnIndex++;
			}
			SaveToPdf.SavePdf(info);
		}
	}
}