using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using QC.CTDS.DM.DataStructures;
using QC.CTDS.DM.DataStructures.FormatDescriptorStructure;
using QC.CTDS.DM.DataStructures.InputDataStructure;
using QC.CTDS.DM.DataStructures.OutputDataStructure;
using QC.CTDS.DM.SharedLibrary;

namespace QC.CTDS.DM.DataProcessor;

public class DataProcessor
{
	private DescriptorAppliedData outputData = new DescriptorAppliedData();

	private InputData inputData;

	private ReportSettings reportSettings;

	public Action<string, LogType> OnWriteLog;

	private List<string> enabledCharts = new List<string>();

	public List<string> EnabledCharts
	{
		get
		{
			return enabledCharts;
		}
		set
		{
			if (value != null)
			{
				enabledCharts = value;
			}
		}
	}

	private void WriteLog(string message, LogType logType)
	{
		if (OnWriteLog != null)
		{
			OnWriteLog(message, logType);
		}
	}

	public DescriptorAppliedData TransformData(InputData inputData, ReportSettings reportSettings, FormatDescriptorCollection formatDescColl)
	{
		Stopwatch stopwatch = new Stopwatch();
		stopwatch.Start();
		FormatDescriptor formatDescriptor = null;
		if (inputData != null && inputData.TestInfoDict != null && inputData.TestInfoDict.Count > 0 && formatDescColl.FormatDescriptors != null && formatDescColl.FormatDescriptors.Count > 0)
		{
			formatDescriptor = formatDescColl.FormatDescriptors[0];
			this.inputData = inputData;
			this.reportSettings = reportSettings;
			if (formatDescriptor.GlobalParameterList != null && formatDescriptor.GlobalParameterList.Count > 0)
			{
				foreach (GlobalParameter gParameter in formatDescriptor.GlobalParameterList.Where((GlobalParameter gParam) => !string.IsNullOrEmpty(gParam.TestName) && !string.IsNullOrEmpty(gParam.ParameterName)))
				{
					if (!inputData.TestInfoDict.ContainsKey(gParameter.TestName))
					{
						continue;
					}
					TestInfo testInfo = inputData.TestInfoDict[gParameter.TestName];
					IEnumerable<TestRunInfo> enumerable = testInfo.TestRunsList.Where((TestRunInfo tInfo) => tInfo.ParamsDict.ContainsKey(gParameter.ParameterName));
					if (enumerable == null || enumerable.Count() <= 0)
					{
						continue;
					}
					foreach (TestRunInfo item in enumerable)
					{
						ParamInfo paramInfo = item.ParamsDict[gParameter.ParameterName];
						if (double.IsNaN(paramInfo.Val))
						{
							item.UnitInfo.UnitDataItemsDict[gParameter.ParameterName] = paramInfo.StrVal;
						}
						else
						{
							item.UnitInfo.UnitDataItemsDict[gParameter.ParameterName] = paramInfo.Val.ToString();
						}
					}
				}
			}
			outputData.GlobalExcelDisplayProperties = formatDescriptor.GlobalExcelDisplayProperties;
			IEnumerable<TestInfo> source = inputData.TestInfoDict.Select((KeyValuePair<string, TestInfo> keyPair) => keyPair.Value);
			CommonFunctions.RunForEachLoop(reportSettings.RunInSequentialMode, source, delegate(TestInfo testinfo)
			{
				CalculateHasParamFailed(testinfo.TestRunsList);
			});
			outputData.FormatDescriptorContent = formatDescriptor.GetFormatDescriptorString();
			outputData.UnitInfoDict = inputData.UnitInfoDict;
			List<OutputGroupSetDescriptor> fdSelectedOutputGroupSets = new List<OutputGroupSetDescriptor>(formatDescriptor.OutputGroupSet.Where((OutputGroupSetDescriptor outGrpSet) => outGrpSet.IsChecked != false) ?? new List<OutputGroupSetDescriptor>());
			List<OutputGroupSet>[] outputGroupSetArray = new List<OutputGroupSet>[fdSelectedOutputGroupSets.Count()];
			CommonFunctions.RunLoop(reportSettings.RunInSequentialMode, 0, fdSelectedOutputGroupSets.Count, delegate(int i)
			{
				outputGroupSetArray[i] = ProcessFdOutputGroupSet(fdSelectedOutputGroupSets[i]);
			});
			for (int j = 0; j < outputGroupSetArray.Length; j++)
			{
				outputData.OutputGroupSetList.AddRange(outputGroupSetArray[j].Where((OutputGroupSet grpSet) => grpSet != null && grpSet.OutputGroupList.Count > 0));
			}
		}
		stopwatch.Stop();
		WriteLog("Time taken to process data: " + stopwatch.Elapsed.ToString(), LogType.Status);
		return outputData;
	}

	private List<OutputGroupSet> ProcessFdOutputGroupSet(OutputGroupSetDescriptor fdGroupSetDescriptor)
	{
		List<OutputGroupSet> list = new List<OutputGroupSet>();
		List<TestRunInfo> testFilteredSourceData = DataProcessorUtils.GetTestFilteredSourceData(from res in fdGroupSetDescriptor.GetResultSets()
			where !string.IsNullOrEmpty(res.testID) && !string.IsNullOrEmpty(res.resID)
			select res, inputData);
		if (testFilteredSourceData.Count > 0)
		{
			if (fdGroupSetDescriptor.Discriminator1.Count > 0 || fdGroupSetDescriptor.Filter.Count > 0)
			{
				List<DiscGroup> filteredSourceData = DataProcessorUtils.GetFilteredSourceData(fdGroupSetDescriptor, testFilteredSourceData, fdGroupSetDescriptor.sort);
				if (filteredSourceData.Count > 0)
				{
					foreach (DiscGroup item in filteredSourceData)
					{
						list.Add(ProcessSingleFdOutputGroupSet(fdGroupSetDescriptor, item.TestItems, item.GrpName));
					}
				}
			}
			else
			{
				list.Add(ProcessSingleFdOutputGroupSet(fdGroupSetDescriptor, testFilteredSourceData));
			}
		}
		return list;
	}

	private OutputGroupSet ProcessSingleFdOutputGroupSet(OutputGroupSetDescriptor fdGroupSetDescriptor, List<TestRunInfo> testRuns, string grpSetNameSuffix = null)
	{
		new List<OutputGroupSet>();
		OutputGroupSet outputGroupSet = new OutputGroupSet();
		if (!string.IsNullOrEmpty(grpSetNameSuffix))
		{
			outputGroupSet.Name = fdGroupSetDescriptor.Name + " " + grpSetNameSuffix;
		}
		else
		{
			outputGroupSet.Name = fdGroupSetDescriptor.Name;
		}
		outputGroupSet.Width = fdGroupSetDescriptor.SheetWidth;
		OutputGroup[] outputGrpArray = null;
		List<GroupSetDescriptor> selectedGroupSetDescriptors = fdGroupSetDescriptor.GetSelectedGroupSetDescriptors();
		ConcurrentQueue<Exception> descriptorException = new ConcurrentQueue<Exception>();
		if (selectedGroupSetDescriptors != null && selectedGroupSetDescriptors.Count > 0)
		{
			outputGrpArray = new OutputGroup[selectedGroupSetDescriptors.Count];
			CommonFunctions.RunLoop(reportSettings.RunInSequentialMode, 0, selectedGroupSetDescriptors.Count, delegate(int i)
			{
				try
				{
					IDescriptorProcessor descriptorProcessor = DescriptorProcessorFactory.CreateDescriptorProcessor(selectedGroupSetDescriptors[i], enabledCharts);
					if (descriptorProcessor != null)
					{
						OutputGroup outputGroup = descriptorProcessor.ProcessDescriptorData(reportSettings, selectedGroupSetDescriptors[i], testRuns);
						if (outputGroup != null && outputGroup.OutputDataList.Count > 0)
						{
							outputGrpArray[i] = outputGroup;
						}
					}
				}
				catch (Exception ex)
				{
					Exception item = new Exception("There was an error Applying the format descriptor " + ex.Message);
					descriptorException.Enqueue(item);
				}
			});
		}
		if (outputGrpArray != null)
		{
			outputGroupSet.OutputGroupList.AddRange(outputGrpArray.Where((OutputGroup grp) => grp != null));
		}
		if (descriptorException != null && descriptorException.Count > 0)
		{
			foreach (Exception item2 in descriptorException)
			{
				if (item2.InnerException != null && item2.Message != null)
				{
					OnWriteLog(item2.Message + Environment.NewLine + "Error Detail: " + item2.InnerException.Message, LogType.Error);
				}
				else
				{
					OnWriteLog(item2.Message, LogType.Error);
				}
			}
		}
		return outputGroupSet;
	}

	private void CalculateHasParamFailed(List<TestRunInfo> runInfoList)
	{
		if (runInfoList == null || runInfoList.Count <= 0)
		{
			return;
		}
		for (int i = 0; i < runInfoList.Count; i++)
		{
			(from par in runInfoList[i].ParamsDict
				where par.Value != null && par.Value is OutputParamInfo
				select new
				{
					OutputParam = (OutputParamInfo)par.Value
				})?.ForEach(pInfo =>
			{
				pInfo.OutputParam.SaveParamFailedState(reportSettings.CustomLimitTypes);
			});
		}
	}
}
