using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;

namespace QTMDataFormat;

public class PivotTableGenerator
{
	protected List<string> rowGroupingFields = new List<string>();

	protected List<string> columnGroupingFields = new List<string>();

	private string valueField = "";

	private DataTable sourceDataTable;

	private DataTable pivotedDataTable;

	private int rowGroupingColumnStartIndex = -1;

	private int rowGroupingColumnEndIndex = -1;

	public List<string> RowGroupingFields
	{
		get
		{
			return rowGroupingFields;
		}
		set
		{
			rowGroupingFields = value;
		}
	}

	public List<string> ColumnGroupingFields
	{
		get
		{
			return columnGroupingFields;
		}
		set
		{
			columnGroupingFields = value;
		}
	}

	public string ValueField
	{
		get
		{
			return valueField;
		}
		set
		{
			valueField = value;
		}
	}

	public DataTable SourceDataTable => sourceDataTable;

	public DataTable PivotedDataTable
	{
		get
		{
			return pivotedDataTable;
		}
		set
		{
			pivotedDataTable = value;
		}
	}

	public int RowGroupingColumnStartIndex
	{
		get
		{
			return rowGroupingColumnStartIndex;
		}
		protected set
		{
			rowGroupingColumnStartIndex = value;
		}
	}

	public int RowGroupingColumnEndIndex
	{
		get
		{
			return rowGroupingColumnEndIndex;
		}
		protected set
		{
			rowGroupingColumnEndIndex = value;
		}
	}

	public event MultipleValuesOccuredEventHandler MultipleValuesOccured;

	public void Pivot(DataTable dataTable)
	{
		Pivot(dataTable, null, null);
	}

	public void Pivot(DataTable dataTable, BackgroundWorker backgroundWorker, DoWorkEventArgs e)
	{
		pivotedDataTable = new DataTable();
		DataColumn dataColumn = null;
		DataColumn dataColumn2 = null;
		DataColumn dataColumn3 = null;
		string name = string.Empty;
		string name2 = string.Empty;
		try
		{
			if (backgroundWorker != null)
			{
				if (backgroundWorker.WorkerSupportsCancellation && backgroundWorker.CancellationPending)
				{
					throw new Exception("User cancelled the operation.");
				}
				if (backgroundWorker.WorkerReportsProgress)
				{
					backgroundWorker.ReportProgress(0, "Calculating Rows based on grouping criteria ....");
				}
			}
			DataTable dataTable2 = dataTable.DefaultView.ToTable(distinct: true, rowGroupingFields.ToArray());
			StringBuilder stringBuilder = new StringBuilder();
			string text = ",";
			StringBuilder stringBuilder2 = new StringBuilder();
			string text2 = " + ";
			foreach (string rowGroupingField in rowGroupingFields)
			{
				stringBuilder.Append("[");
				stringBuilder.Append(rowGroupingField);
				stringBuilder.Append("]");
				stringBuilder.Append(text);
				stringBuilder2.Append("ISNULL([");
				stringBuilder2.Append(rowGroupingField);
				stringBuilder2.Append("],'')");
				stringBuilder2.Append(text2);
			}
			stringBuilder.Remove(stringBuilder.Length - text.Length, text.Length);
			stringBuilder2.Remove(stringBuilder2.Length - text2.Length, text2.Length);
			dataTable2.DefaultView.Sort = stringBuilder.ToString() + " ASC";
			dataTable2 = dataTable2.DefaultView.ToTable();
			string expression = stringBuilder2.ToString();
			dataColumn = new DataColumn("CorrelatorRowKeyColumn", typeof(string));
			dataColumn.Expression = expression;
			dataTable.Columns.Add(dataColumn);
			pivotedDataTable = dataTable2.Copy();
			dataColumn3 = new DataColumn("CorrelatorRowKeyColumn", typeof(string));
			dataColumn3.Expression = expression;
			pivotedDataTable.DefaultView.Sort = stringBuilder.ToString() + " ASC";
			pivotedDataTable.Columns.Add(dataColumn3);
			if (backgroundWorker != null)
			{
				if (backgroundWorker.WorkerSupportsCancellation && backgroundWorker.CancellationPending)
				{
					throw new Exception("User cancelled the operation.");
				}
				if (backgroundWorker.WorkerReportsProgress)
				{
					backgroundWorker.ReportProgress(0, "Calculating Columns based on grouping criteria ....");
				}
			}
			DataTable dataTable3 = dataTable.DefaultView.ToTable(distinct: true, columnGroupingFields.ToArray());
			StringBuilder stringBuilder3 = new StringBuilder();
			foreach (string columnGroupingField in columnGroupingFields)
			{
				stringBuilder3.Append(columnGroupingField);
				stringBuilder3.Append(",");
			}
			stringBuilder3.Remove(stringBuilder3.Length - 1, 1);
			dataTable3.DefaultView.Sort = stringBuilder3.ToString() + " ASC";
			dataTable3 = dataTable3.DefaultView.ToTable();
			string text3 = stringBuilder3.ToString();
			text3 = text3.Replace(",", " + '_' + ");
			dataColumn2 = new DataColumn("CorrelatorColumnKeyColumn", typeof(string));
			dataColumn2.Expression = text3;
			dataTable.Columns.Add(dataColumn2);
			Type dataType = typeof(string);
			if (dataTable.Columns.Contains(valueField))
			{
				dataType = dataTable.Columns[valueField].DataType;
			}
			int num = 0;
			foreach (DataRow row in dataTable3.Rows)
			{
				StringBuilder stringBuilder4 = new StringBuilder();
				foreach (DataColumn column in dataTable3.Columns)
				{
					stringBuilder4.Append(Convert.ToString(row[column]));
					stringBuilder4.Append("_");
				}
				stringBuilder4.Remove(stringBuilder4.Length - 1, 1);
				DataColumn dataColumn4 = new DataColumn(stringBuilder4.ToString(), dataType);
				dataColumn4.AllowDBNull = true;
				pivotedDataTable.Columns.Add(dataColumn4);
				if (num == 0)
				{
					name = dataColumn4.ColumnName;
				}
				if (num == dataTable3.Rows.Count - 1)
				{
					name2 = dataColumn4.ColumnName;
				}
				num++;
			}
			int count = pivotedDataTable.Rows.Count;
			int num2 = 0;
			foreach (DataRow row2 in pivotedDataTable.Rows)
			{
				string arg = Convert.ToString(row2[dataColumn3.ColumnName]);
				foreach (DataColumn column2 in pivotedDataTable.Columns)
				{
					if (rowGroupingFields.Contains(column2.ColumnName) || !(column2.ColumnName != dataColumn3.ColumnName))
					{
						continue;
					}
					string filterExpression = $"CorrelatorRowKeyColumn = '{arg}' AND CorrelatorColumnKeyColumn = '{column2.ColumnName}'";
					DataRow[] array = dataTable.Select(filterExpression);
					if (array.Length <= 0)
					{
						continue;
					}
					if (array.Length == 1)
					{
						row2[column2] = array[0][valueField];
						continue;
					}
					List<DataRow> list = new List<DataRow>();
					StringBuilder stringBuilder5 = new StringBuilder();
					DataRow[] array2 = array;
					foreach (DataRow item in array2)
					{
						if (this.MultipleValuesOccured != null)
						{
							list.Add(item);
							continue;
						}
						stringBuilder5.Append(Convert.ToString(array[0][valueField]));
						stringBuilder5.Append(",");
					}
					if (this.MultipleValuesOccured != null)
					{
						MultipleValuesOccuredEventArgs multipleValuesOccuredEventArgs = new MultipleValuesOccuredEventArgs(list, valueField);
						this.MultipleValuesOccured(this, multipleValuesOccuredEventArgs);
						row2[column2] = multipleValuesOccuredEventArgs.Result;
					}
					else
					{
						stringBuilder5.Remove(stringBuilder5.Length - 1, 1);
						row2[column2] = stringBuilder5.ToString();
					}
				}
				num2++;
				if (backgroundWorker == null)
				{
					continue;
				}
				if (backgroundWorker.WorkerSupportsCancellation && backgroundWorker.CancellationPending)
				{
					throw new Exception("User cancelled the operation.");
				}
				if (backgroundWorker.WorkerReportsProgress)
				{
					int num3 = num2 * 100 / count;
					if (num3 > 0 && num3 % 10 == 0)
					{
						backgroundWorker.ReportProgress(num3, "Calculating values of the Pivot Table ....");
					}
				}
			}
		}
		catch (Exception ex)
		{
			throw ex;
		}
		finally
		{
			if (dataColumn != null && dataTable.Columns.Contains(dataColumn.ColumnName))
			{
				dataTable.Columns.Remove(dataColumn);
			}
			if (dataColumn2 != null && dataTable.Columns.Contains(dataColumn2.ColumnName))
			{
				dataTable.Columns.Remove(dataColumn2);
			}
			if (dataColumn3 != null && pivotedDataTable.Columns.Contains(dataColumn3.ColumnName))
			{
				pivotedDataTable.Columns.Remove(dataColumn3);
			}
			if (pivotedDataTable.Columns.Contains(name))
			{
				RowGroupingColumnStartIndex = pivotedDataTable.Columns[name].Ordinal;
			}
			if (pivotedDataTable.Columns.Contains(name2))
			{
				RowGroupingColumnEndIndex = pivotedDataTable.Columns[name2].Ordinal;
			}
		}
	}
}
