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

internal class ScatteredDescriptorProcessor : IDescriptorProcessor
{
	private ScatterOutputGroupDescriptor fdScatteredChartDescriptor;

	internal ReportSettings reportSettings;

	internal List<TestRunInfo> testRuns;

	internal ScatteredDescriptorProcessor()
	{
	}

	public OutputGroup ProcessDescriptorData(ReportSettings settings, GroupSetDescriptor groupSetDesc, List<TestRunInfo> testRuns)
	{
		reportSettings = settings;
		fdScatteredChartDescriptor = groupSetDesc as ScatterOutputGroupDescriptor;
		this.testRuns = testRuns;
		if (reportSettings.FailureAnalysis)
		{
			return null;
		}
		if (fdScatteredChartDescriptor == null)
		{
			throw new Exception("Unsopported descriptor type");
		}
		OutputGroup outputGroup = new OutputGroup();
		outputGroup.Name = fdScatteredChartDescriptor.Name;
		if (fdScatteredChartDescriptor.OGDisplayProperties != null && fdScatteredChartDescriptor.OGDisplayProperties.Count > 0)
		{
			outputGroup.DisplayProp = fdScatteredChartDescriptor.OGDisplayProperties[0];
		}
		testRuns = DataProcessorUtils.GetTestFilteredSourceData(fdScatteredChartDescriptor.Series.Where((ScatteredChartSeries series) => !string.IsNullOrEmpty(series.testID) && series.DepVar != null && !string.IsNullOrEmpty(series.DepVar.IdVariable) && series.IndVar != null && !string.IsNullOrEmpty(series.IndVar.IdVariable)), testRuns);
		if (testRuns.Count > 0)
		{
			if (fdScatteredChartDescriptor.Discriminator1.Count > 0 || fdScatteredChartDescriptor.Filter.Count > 0)
			{
				List<DiscGroup> chartGroupedItems = DataProcessorUtils.GetFilteredSourceData(fdScatteredChartDescriptor, testRuns, fdScatteredChartDescriptor.sort);
				if (chartGroupedItems.Count <= 0)
				{
					return outputGroup;
				}
				ScatteredData[] scatteredDataArray = new ScatteredData[chartGroupedItems.Count];
				CommonFunctions.RunLoop(reportSettings.RunInSequentialMode, 0, chartGroupedItems.Count, delegate(int index)
				{
					scatteredDataArray[index] = GenerateScatteredData(chartGroupedItems[index].TestItems, chartGroupedItems[index].GrpName);
				});
				for (int i = 0; i < scatteredDataArray.Length; i++)
				{
					if (scatteredDataArray[i] != null && scatteredDataArray[i].DataTbl.RowCount > 0 && scatteredDataArray[i].DataTbl.ColumnCount > 1)
					{
						outputGroup.OutputDataList.Add(scatteredDataArray[i]);
					}
				}
			}
			else
			{
				ScatteredData scatteredData = GenerateScatteredData(testRuns);
				if (scatteredData.DataTbl.RowCount > 0 && scatteredData.DataTbl.ColumnCount > 1)
				{
					outputGroup.OutputDataList.Add(scatteredData);
				}
			}
		}
		return outputGroup;
	}

	private ScatteredData GenerateScatteredData(List<TestRunInfo> testRuns, string combinedSeriesGrpString = null)
	{
		ScatteredData scatteredData = new ScatteredData();
		if (testRuns.Count > 0)
		{
			if (fdScatteredChartDescriptor.OGDisplayProperties != null && fdScatteredChartDescriptor.OGDisplayProperties.Count > 0)
			{
				OuputGraphDisplayProperties ouputGraphDisplayProperties = fdScatteredChartDescriptor.OGDisplayProperties[0];
				if (ouputGraphDisplayProperties.XAxis.Count > 0)
				{
					if (double.TryParse(ouputGraphDisplayProperties.XAxis[0].min, out var result))
					{
						scatteredData.XAxisMinScale = result;
						scatteredData.UseAutoScaleXAxis = false;
					}
					if (double.TryParse(ouputGraphDisplayProperties.XAxis[0].max, out var result2))
					{
						scatteredData.XAxisMaxScale = result2;
						scatteredData.UseAutoScaleXAxis = false;
					}
				}
				foreach (Axis item in ouputGraphDisplayProperties.YAxis)
				{
					double result3;
					double result4;
					if (item.index == 1)
					{
						if (double.TryParse(item.min, out result3))
						{
							scatteredData.YAxisMinScale = result3;
							scatteredData.UseAutoScaleYAxis = false;
						}
						if (double.TryParse(item.max, out result4))
						{
							scatteredData.YAxisMaxScale = result4;
							scatteredData.UseAutoScaleYAxis = false;
						}
					}
					else if (item.index == 2)
					{
						if (double.TryParse(item.min, out result3))
						{
							scatteredData.SecYAxisMinScale = result3;
							scatteredData.UseAutoScaleSecYAxis = false;
						}
						if (double.TryParse(item.max, out result4))
						{
							scatteredData.SecYAxisMaxScale = result4;
							scatteredData.UseAutoScaleSecYAxis = false;
						}
					}
				}
			}
			if (!string.IsNullOrEmpty(combinedSeriesGrpString))
			{
				scatteredData.Name = fdScatteredChartDescriptor.Name + " : " + combinedSeriesGrpString;
			}
			else
			{
				scatteredData.Name = fdScatteredChartDescriptor.Name;
			}
			scatteredData.XAxisTitle = fdScatteredChartDescriptor.xName;
			scatteredData.YAxisTitle = fdScatteredChartDescriptor.yName;
			scatteredData.SecYAxisTitle = fdScatteredChartDescriptor.secYName;
			AddHeaderData(scatteredData);
			foreach (ScatteredChartSeries scatSeries in fdScatteredChartDescriptor.Series.Where((ScatteredChartSeries series) => !string.IsNullOrEmpty(series.testID) && series.DepVar != null && !string.IsNullOrEmpty(series.DepVar.IdVariable) && series.IndVar != null && !string.IsNullOrEmpty(series.IndVar.IdVariable)))
			{
				List<TestRunInfo> testFilteredSourceData = DataProcessorUtils.GetTestFilteredSourceData(new ScatteredChartSeries[1] { scatSeries }, testRuns);
				List<TestRunInfo> source = testFilteredSourceData;
				Func<TestRunInfo, bool> predicate = (TestRunInfo runinfo) => runinfo.ContainsParam(scatSeries.DepVar.IdVariable) && runinfo.ContainsParam(scatSeries.IndVar.IdVariable);
				testFilteredSourceData = source.Where(predicate).ToList();
				if ((reportSettings.AllFailureAnalysis && !testFilteredSourceData.Any((TestRunInfo runInfo) => runInfo.HasParamFailed(scatSeries.DepVar.IdVariable))) || testFilteredSourceData.Count <= 0)
				{
					continue;
				}
				TestRunInfo testRunInfo = testFilteredSourceData.Find((TestRunInfo runinfo) => runinfo.ContainsParam(scatSeries.DepVar.IdVariable));
				_ = testRunInfo.GetParamValue(scatSeries.DepVar.IdVariable).ParamUnit;
				if (scatSeries.Discriminator1.Count > 0 || scatSeries.Filter.Count > 0)
				{
					List<DiscGroup> filteredSourceData = DataProcessorUtils.GetFilteredSourceData(scatSeries, testFilteredSourceData, scatSeries.sort);
					if (filteredSourceData.Count <= 0)
					{
						continue;
					}
					foreach (DiscGroup item2 in filteredSourceData)
					{
						AddScatteredSeriesGrpData(scatteredData, scatSeries, item2.TestItems, item2.GrpName);
					}
				}
				else
				{
					AddScatteredSeriesGrpData(scatteredData, scatSeries, testFilteredSourceData);
				}
			}
			double minVal = double.NaN;
			double maxVal = double.NaN;
			if (!scatteredData.UseAutoScaleXAxis)
			{
				double xAxisMinScale = (scatteredData.XAxisMaxScale = double.NaN);
				scatteredData.XAxisMinScale = xAxisMinScale;
			}
			else
			{
				if (!double.IsNaN(scatteredData.XAxisMaxScale))
				{
					maxVal = scatteredData.XAxisMaxScale;
				}
				if (!double.IsNaN(scatteredData.XAxisMinScale))
				{
					minVal = scatteredData.XAxisMinScale;
				}
				CommonFunctions.RoundSmart(ref minVal, ref maxVal, forceRes: false, 0);
				scatteredData.XAxisMaxScale = maxVal;
				scatteredData.XAxisMinScale = minVal;
			}
			maxVal = (minVal = double.NaN);
			if (!scatteredData.UseAutoScaleYAxis)
			{
				double yAxisMinScale = (scatteredData.YAxisMaxScale = double.NaN);
				scatteredData.YAxisMinScale = yAxisMinScale;
			}
			else
			{
				if (!double.IsNaN(scatteredData.YAxisMaxScale))
				{
					maxVal = scatteredData.YAxisMaxScale;
				}
				if (!double.IsNaN(scatteredData.YAxisMinScale))
				{
					minVal = scatteredData.YAxisMinScale;
				}
				CommonFunctions.RoundSmart(ref minVal, ref maxVal, forceRes: false, 0);
				scatteredData.YAxisMaxScale = maxVal;
				scatteredData.YAxisMinScale = minVal;
			}
			maxVal = (minVal = double.NaN);
			if (!scatteredData.UseAutoScaleSecYAxis)
			{
				double secYAxisMinScale = (scatteredData.SecYAxisMaxScale = double.NaN);
				scatteredData.SecYAxisMinScale = secYAxisMinScale;
			}
			else
			{
				if (!double.IsNaN(scatteredData.SecYAxisMaxScale))
				{
					maxVal = scatteredData.SecYAxisMaxScale;
				}
				if (!double.IsNaN(scatteredData.SecYAxisMinScale))
				{
					minVal = scatteredData.SecYAxisMinScale;
				}
				CommonFunctions.RoundSmart(ref minVal, ref maxVal, forceRes: false, 0);
				scatteredData.SecYAxisMaxScale = maxVal;
				scatteredData.SecYAxisMinScale = minVal;
			}
		}
		return scatteredData;
	}

	private void AddScatteredSeriesGrpData(ScatteredData scatteredData, ScatteredChartSeries scatSeries, List<TestRunInfo> testRuns, string combinedGrpName = null)
	{
		if (testRuns.Count > 0)
		{
			if (scatSeries.groupByTC)
			{
				GroupByTestCase(scatteredData, scatSeries, testRuns, combinedGrpName);
			}
			else if (scatSeries.groupAll)
			{
				GroupAll(scatteredData, scatSeries, testRuns, combinedGrpName);
			}
			else
			{
				GroupByUnitTestRunIndex(scatteredData, scatSeries, testRuns, combinedGrpName);
			}
		}
	}

	private void AppendTestRunData(ScatteredData scatteredData, ScatteredChartSeries scatSeries, IEnumerable<TestRunInfo> testRuns, string combinedGrpName)
	{
		if (testRuns.Count() <= 0)
		{
			return;
		}
		int num = 3;
		long runId = testRuns.ElementAt(0).RunId;
		string text = ((!string.IsNullOrEmpty(scatSeries.GroupName)) ? (scatSeries.DepVar.IdVariable + "_" + scatSeries.GroupName) : scatSeries.DepVar.IdVariable);
		string val = string.Join(" ", new string[3]
		{
			text,
			combinedGrpName,
			runId.ToString()
		}.Where((string str) => !string.IsNullOrEmpty(str)));
		string seriesNameWithoutRunId = string.Join(" ", new string[2] { text, combinedGrpName }.Where((string str) => !string.IsNullOrEmpty(str)));
		if (!scatteredData.ResultDisplayList.All((Tuple<string, string, SeriesDisplayProperties> rd) => rd.Item1 + " " + rd.Item2 == seriesNameWithoutRunId) || scatteredData.ResultDisplayList.Count == 0)
		{
			scatteredData.ResultDisplayList.Add(new Tuple<string, string, SeriesDisplayProperties>(text, combinedGrpName, scatSeries.DisplayProperties));
		}
		int columnIndex = scatteredData.DataTbl.AddColumn();
		scatteredData.DataTbl.SetValue(val, 0, columnIndex);
		scatteredData.DataTbl.SetValue(scatSeries.IndVar.IdVariable, 1, columnIndex);
		scatteredData.DataTbl.SetValue(combinedGrpName, 2, columnIndex);
		int columnIndex2 = scatteredData.DataTbl.AddColumn();
		scatteredData.DataTbl.SetValue(scatSeries.DepVar.IdVariable, 1, columnIndex2);
		int num2 = -1;
		int num3 = -1;
		double num4 = double.NaN;
		foreach (TestRunInfo testRun in testRuns)
		{
			if (num >= scatteredData.DataTbl.RowCount)
			{
				scatteredData.DataTbl.AddNewRow();
			}
			if (double.IsNaN(testRun.GetParamValue(scatSeries.IndVar.IdVariable).Val))
			{
				scatteredData.DataTbl.SetValue(testRun.GetParamValue(scatSeries.IndVar.IdVariable).StrVal, num, columnIndex);
			}
			else
			{
				num4 = testRun.GetParamValue(scatSeries.IndVar.IdVariable).Val;
				if (scatteredData.UseAutoScaleXAxis)
				{
					if (double.IsNaN(scatteredData.XAxisMaxScale) || scatteredData.XAxisMaxScale < num4)
					{
						scatteredData.XAxisMaxScale = num4;
					}
					if (double.IsNaN(scatteredData.XAxisMinScale) || scatteredData.XAxisMinScale > num4)
					{
						scatteredData.XAxisMinScale = num4;
					}
				}
				scatteredData.DataTbl.SetValue(num4.ToString(), num, columnIndex);
			}
			ParamInfo paramValue = testRun.GetParamValue(scatSeries.DepVar.IdVariable);
			OutputParamInfo outputParamInfo = null;
			if (paramValue != null)
			{
				outputParamInfo = ((!(paramValue is OutputParamInfo)) ? new OutputParamInfo(paramValue) : (paramValue as OutputParamInfo));
			}
			if (outputParamInfo != null)
			{
				if (!double.IsNaN(outputParamInfo.Val))
				{
					if (scatSeries.DisplayProperties.axisIndex != 2 && scatteredData.UseAutoScaleYAxis)
					{
						if (double.IsNaN(scatteredData.YAxisMaxScale) || scatteredData.YAxisMaxScale < outputParamInfo.Val)
						{
							scatteredData.YAxisMaxScale = outputParamInfo.Val;
						}
						if (double.IsNaN(scatteredData.YAxisMinScale) || scatteredData.YAxisMinScale > outputParamInfo.Val)
						{
							scatteredData.YAxisMinScale = outputParamInfo.Val;
						}
					}
					else if (scatSeries.DisplayProperties.axisIndex == 2 && scatteredData.UseAutoScaleSecYAxis)
					{
						if (double.IsNaN(scatteredData.SecYAxisMaxScale) || scatteredData.SecYAxisMaxScale < outputParamInfo.Val)
						{
							scatteredData.SecYAxisMaxScale = outputParamInfo.Val;
						}
						if (double.IsNaN(scatteredData.SecYAxisMinScale) || scatteredData.SecYAxisMinScale > outputParamInfo.Val)
						{
							scatteredData.SecYAxisMinScale = outputParamInfo.Val;
						}
					}
					scatteredData.DataTbl.SetValue(outputParamInfo.Val.ToString(), num, columnIndex2);
				}
				if (reportSettings.ShowLimitOnScatterPlots && !double.IsNaN(outputParamInfo.MinLimit))
				{
					if (num2 < 0)
					{
						num2 = scatteredData.DataTbl.AddColumn();
						scatteredData.DataTbl.SetValue(scatSeries.DepVar.IdVariable + "_minLim", 1, num2);
					}
					if (scatSeries.DisplayProperties.axisIndex != 2)
					{
						if (double.IsNaN(scatteredData.YAxisMaxScale) || scatteredData.YAxisMaxScale < outputParamInfo.MinLimit)
						{
							scatteredData.YAxisMaxScale = outputParamInfo.MinLimit;
						}
						if (double.IsNaN(scatteredData.YAxisMinScale) || scatteredData.YAxisMinScale > outputParamInfo.MinLimit)
						{
							scatteredData.YAxisMinScale = outputParamInfo.MinLimit;
						}
					}
					else
					{
						if (double.IsNaN(scatteredData.SecYAxisMaxScale) || scatteredData.SecYAxisMaxScale < outputParamInfo.MinLimit)
						{
							scatteredData.SecYAxisMaxScale = outputParamInfo.MinLimit;
						}
						if (double.IsNaN(scatteredData.SecYAxisMinScale) || scatteredData.SecYAxisMinScale > outputParamInfo.MinLimit)
						{
							scatteredData.SecYAxisMinScale = outputParamInfo.MinLimit;
						}
					}
					scatteredData.DataTbl.SetValue(outputParamInfo.MinLimit.ToString(), num, num2);
				}
				if (reportSettings.ShowLimitOnScatterPlots && !double.IsNaN(outputParamInfo.MaxLimit))
				{
					if (num3 < 0)
					{
						num3 = scatteredData.DataTbl.AddColumn();
						scatteredData.DataTbl.SetValue(scatSeries.DepVar.IdVariable + "_maxLim", 1, num3);
					}
					if (scatSeries.DisplayProperties.axisIndex != 2)
					{
						if (double.IsNaN(scatteredData.YAxisMaxScale) || scatteredData.YAxisMaxScale < outputParamInfo.MaxLimit)
						{
							scatteredData.YAxisMaxScale = outputParamInfo.MaxLimit;
						}
						if (double.IsNaN(scatteredData.YAxisMinScale) || scatteredData.YAxisMinScale > outputParamInfo.MaxLimit)
						{
							scatteredData.YAxisMinScale = outputParamInfo.MaxLimit;
						}
					}
					else
					{
						if (double.IsNaN(scatteredData.SecYAxisMaxScale) || scatteredData.SecYAxisMaxScale < outputParamInfo.MaxLimit)
						{
							scatteredData.SecYAxisMaxScale = outputParamInfo.MaxLimit;
						}
						if (double.IsNaN(scatteredData.SecYAxisMinScale) || scatteredData.SecYAxisMinScale > outputParamInfo.MaxLimit)
						{
							scatteredData.SecYAxisMinScale = outputParamInfo.MaxLimit;
						}
					}
					scatteredData.DataTbl.SetValue(outputParamInfo.MaxLimit.ToString(), num, num3);
				}
			}
			num++;
		}
	}

	private void GroupByUnitTestRunIndex(ScatteredData scatteredData, ScatteredChartSeries scatSeries, List<TestRunInfo> testRuns, string combinedGrpName)
	{
		var enumerable = from runInfo in testRuns
			group runInfo by new { runInfo.RunId, runInfo.UnitTestRunIndex };
		if (enumerable.Count() <= 0)
		{
			return;
		}
		foreach (var item in enumerable)
		{
			if (item.All((TestRunInfo runinfo) => !double.IsNaN(runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val)))
			{
				AppendTestRunData(scatteredData, scatSeries, item.OrderBy((TestRunInfo runinfo) => runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val), combinedGrpName);
			}
		}
	}

	private void GroupAll(ScatteredData scatteredData, ScatteredChartSeries scatSeries, List<TestRunInfo> testRuns, string combinedGrpName)
	{
		if (testRuns.TrueForAll((TestRunInfo runinfo) => !double.IsNaN(runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val)))
		{
			AppendTestRunData(scatteredData, scatSeries, testRuns.OrderBy((TestRunInfo runinfo) => runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val), combinedGrpName);
		}
	}

	private void GroupByTestCase(ScatteredData scatteredData, ScatteredChartSeries scatSeries, List<TestRunInfo> testRuns, string combinedGrpName)
	{
		IEnumerable<IGrouping<long, TestRunInfo>> enumerable = from runinfo in testRuns
			group runinfo by runinfo.RunId;
		if (enumerable.Count() <= 0)
		{
			return;
		}
		foreach (IGrouping<long, TestRunInfo> item in enumerable)
		{
			if (item.All((TestRunInfo runinfo) => !double.IsNaN(runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val)))
			{
				AppendTestRunData(scatteredData, scatSeries, item.OrderBy((TestRunInfo runinfo) => runinfo.GetParamValue(scatSeries.IndVar.IdVariable).Val), combinedGrpName);
			}
		}
	}

	private void AddHeaderData(ScatteredData scatteredData)
	{
		scatteredData.DataTbl.AddColumn();
		scatteredData.DataTbl.AddNewRow();
		scatteredData.DataTbl.AddNewRow();
		scatteredData.DataTbl.AddNewRow();
		scatteredData.DataTbl.SetValue("Name", 0, 0);
		scatteredData.DataTbl.SetValue("X,Y", 1, 0);
		scatteredData.DataTbl.SetValue("Conditions", 2, 0);
	}
}
