using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Threading;
using QC.CorpTest.Libraries.QsprSchemaLibrary;
using QC.QTMDotNetKernelInterface;
using QC.QTMDotNetKernelInterface.Environment;
using QTMDataFormat;

namespace QC.QTMToolKit.Tools;

[QTMTestClass]
public class DataFormatGenerator : QSPRTest
{
	public static class ParamtericDataTableColumns
	{
		public const string SessionDataRID = "SessionDataRID";

		public const string UUT_SN = "UUT_SN";

		public const string MCN = "MCN";

		public const string TreeID = "TreeID";

		public const string TesterID = "TesterID";

		public const string TestName = "TestName";

		public const string ParameterName = "ParameterName";

		public const string LowerLimit = "LowerLimit";

		public const string NumValue = "NumValue";

		public const string UpperLimit = "UpperLimit";

		public const string CharValue = "CharValue";

		public const string ExtHyperLink = "Link";

		public const string UOM = "UOM";

		public const string TestResult = "TestResult";

		public const string StartTime = "StartTime";

		public const string StopTime = "StopTime";

		public const string VisitNum = "VisitNum";

		public const string GlobalResult = "GlobalResult";

		public const string DvtFlag = "DvtFlag";

		public const string ScnValue = "ScnValue";

		public const string ArrayParamIndex = "ArrayParamIndex";

		public const string ArrayLowerLimit = "ArrayLowerLimit";

		public const string ArrayResult = "ArrayResult";

		public const string ArrayUpperLimit = "ArrayUpperLimit";

		public const string ArrayParamCharResult = "ArrayParamCharResult";

		public const string RunTitle = "RunTitle";

		public const string PassFail = "PassFail";

		public const string LastVisit = "LastVisit";

		public const string WorkStation = "WorkStation";
	}

	private class FileLastWriteTimeComparer : IComparer<FileInfo>
	{
		public int Compare(FileInfo x, FileInfo y)
		{
			return x.LastWriteTime.CompareTo(y.LastWriteTime);
		}
	}

	private int maxTestCode;

	private char csvSeperator = ',';

	public DataFormatGenerator(QSPREnvironment qsprEnv)
		: base(qsprEnv)
	{
	}

	private string GenerateReportFileName(string TestFlag, string serialNumber, string testBench, DateTime startDateTime, string SlotNumber, string ScenarioVersion)
	{
		return string.Format("{0}#{1}#{2}#{3}#{4}#{5}.rpt", TestFlag, serialNumber, testBench, startDateTime.ToString("yyyyMMdd(HHmmss)"), SlotNumber, ScenarioVersion);
	}

	private Dictionary<string, int> GetTestCodeMapping(string TestMappingFilePath)
	{
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		if (File.Exists(TestMappingFilePath))
		{
			using StreamReader streamReader = new StreamReader(TestMappingFilePath);
			while (!streamReader.EndOfStream)
			{
				string[] array = streamReader.ReadLine().Split(new char[1] { csvSeperator }, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length == 2 && int.TryParse(array[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
				{
					if (maxTestCode < result)
					{
						maxTestCode = result;
					}
					dictionary.Add(array[0], result);
				}
			}
		}
		return dictionary;
	}

	private void WriteTestCodeMapping(Dictionary<string, int> testCodeMapping, string TestMappingFilePath)
	{
		try
		{
			using StreamWriter streamWriter = new StreamWriter(TestMappingFilePath, append: false);
			foreach (KeyValuePair<string, int> item in testCodeMapping)
			{
				streamWriter.WriteLine(item.Key + csvSeperator + item.Value.ToString("X4"));
			}
		}
		catch (Exception)
		{
			Thread.Sleep(5000);
			WriteTestCodeMapping(testCodeMapping, TestMappingFilePath);
		}
	}

	private string GetQsprLogFilePath(string SerialNumber, string QSPRLogFolderPath)
	{
		DirectoryInfo directoryInfo = new DirectoryInfo(QSPRLogFolderPath);
		FileInfo[] files = directoryInfo.GetFiles("*" + SerialNumber + "*.xml");
		string result = null;
		if (files.Length > 0)
		{
			Array.Sort(files, new FileLastWriteTimeComparer());
			result = files[files.Length - 1].FullName;
		}
		return result;
	}

	private string GetQSPRLoopConditions(string QSPRFilePath)
	{
		string result = "";
		if (File.Exists(QSPRFilePath))
		{
			using StreamReader streamReader = new StreamReader(QSPRFilePath);
			result = streamReader.ReadToEnd();
		}
		return result;
	}

	private string GetUnitResult(DataTable qsprData)
	{
		string result = "UNKNOWN";
		if (qsprData != null && qsprData.Rows.Count > 0)
		{
			string text = qsprData.Rows[0]["GlobalResult"].ToString();
			result = ((!(text.ToLower() == "passed")) ? "FAIL" : "PASS");
		}
		return result;
	}

	private void ConfigureQSPRConvertor(QsprConvertor qsprConvertor, string qsprLoopConditions)
	{
		qsprConvertor.Database = "NO DB";
		qsprConvertor.ExtendedData = 0;
		qsprConvertor.LoopConditions = qsprLoopConditions;
		qsprConvertor.MCN = "NA";
		qsprConvertor.RegisteredMachine = Environment.MachineName;
		qsprConvertor.Server = "No Server";
		qsprConvertor.TesterID = "QSPR";
		qsprConvertor.TreeID = "-1";
		qsprConvertor.TreeType = "DVT";
		qsprConvertor.Workstation = Environment.MachineName;
	}

	private static void GetStartStopDateTime(DataTable qsprData, out DateTime startDateTime, out DateTime stopDateTime)
	{
		startDateTime = DateTime.MinValue;
		stopDateTime = DateTime.MinValue;
		if (qsprData != null && qsprData.Rows.Count > 0)
		{
			DateTime.TryParse(qsprData.Rows[0]["StartTime"].ToString(), out startDateTime);
			DateTime.TryParse(qsprData.Rows[0]["StopTime"].ToString(), out stopDateTime);
		}
	}

	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "CSVFileFolderPath", Description = "Folder location to keep the CSV file. CSV File name is same as the XML data file name")]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "SUITELogFolderPath", Description = "The absolute folder path to the SUITE log file generated by the Test tree")]
	[QTMTest(Description = "Converts the SUITE test data in to CSV file format. Place the test after the FinalizeDataLogging test where SubSys DLL are used", CanAddToTestPlan = true)]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "SUITELoopConditonsFilePath", Description = "CSV file containing SUITE loop conditions. If left blank, all the input conditions will be treated as LoopConditions.", DisplayHint = DisplayHints.FILE)]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "SerialNumber", Description = "Serial number")]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "appendPassFailInfo", Description = "Appends P or F at the end of file name")]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "ErrorMessage", Description = "Information on any error during CSV file creation")]
	public bool GenerateSUITEDataInCSVFormat(string SUITELogFolderPath, string CSVFileFolderPath, string SUITELoopConditonsFilePath, string SerialNumber, bool appendPassFailInfo, out string ErrorMessage)
	{
		bool result = true;
		ErrorMessage = string.Empty;
		bool isCancelled = false;
		try
		{
			string qSPRLoopConditions = GetQSPRLoopConditions(SUITELoopConditonsFilePath);
			QsprConvertor qsprConvertor = new QsprConvertor();
			ConfigureQSPRConvertor(qsprConvertor, qSPRLoopConditions);
			string qsprLogFilePath = GetQsprLogFilePath(SerialNumber, SUITELogFolderPath);
			DataTable dataTable = qsprConvertor.GenerateQDMFormattedData(qsprLogFilePath, pivotLoopConditions: false, null, null, string.Empty);
			dataTable.Copy();
			dataTable = FormatFunctions.ParseLoopConditions(dataTable, removedelimitedcolumn: false, out var _, out ErrorMessage);
			FormatArgs fargs = new FormatArgs();
			fargs.DataSource = dataTable;
			fargs.SelectedFormatOption = FormatFunctions.FormatOptions.LongView;
			FormatFunctions.GetDataInLongView(ref fargs, out ErrorMessage, ref isCancelled);
			GetStartStopDateTime(dataTable, out var _, out var _);
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(qsprLogFilePath);
			if (appendPassFailInfo)
			{
				string text = ((GetUnitResult(dataTable) == "PASS") ? "P" : "F");
				fileNameWithoutExtension = fileNameWithoutExtension + "_" + text + ".csv";
			}
			else
			{
				fileNameWithoutExtension += ".csv";
			}
			string path = Path.Combine(CSVFileFolderPath, fileNameWithoutExtension);
			using StreamWriter streamWriter = new StreamWriter(path, append: false);
			RemoveExtraCsvColumns(dataTable);
			for (int i = 0; i < dataTable.Columns.Count; i++)
			{
				streamWriter.Write(dataTable.Columns[i].ColumnName + ",");
			}
			streamWriter.WriteLine();
			for (int j = 0; j < dataTable.Rows.Count; j++)
			{
				streamWriter.WriteLine(JoinDataWithDelimiter(dataTable.Rows[j].ItemArray, ","));
			}
		}
		catch (Exception ex)
		{
			ErrorMessage = ex.ToString();
			result = false;
		}
		return result;
	}

	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "SUITELogFolderPath", Description = "The absolute folder path to the QSPR log file generated by the Test tree")]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "DeleteOriginal", Description = "Whether or not to delete the original log file", DefaultValue = "False")]
	[QTMTest(Description = "Rename the QSPR log file to a descriptive file name including the temperature and voltage. Move the test if requested.", CanAddToTestPlan = true)]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "DestinationDirectory", Description = "Optional: The directory where the log file should be moved")]
	[QTMParameter(IOType = ParameterIOType.Input, ArgumentName = "SerialNumber", Description = "Serial number")]
	public bool RenameSUITELogFileToFormattedName(string SUITELogFolderPath, string SerialNumber, string DestinationDirectory, bool DeleteOriginal, out string ErrorMessage)
	{
		ErrorMessage = string.Empty;
		try
		{
			string qsprLogFilePath = GetQsprLogFilePath(SerialNumber, SUITELogFolderPath);
			if (qsprLogFilePath == null)
			{
				ErrorMessage = "No log file found for serial number \"" + SerialNumber + "\"";
				base.Env.DebugMessage.Write("Temp", ErrorMessage);
				return false;
			}
			if (DestinationDirectory == null || DestinationDirectory.Length == 0)
			{
				DestinationDirectory = Path.GetDirectoryName(qsprLogFilePath);
			}
			if (!Directory.Exists(DestinationDirectory))
			{
				Directory.CreateDirectory(DestinationDirectory);
			}
			QsprConvertor qsprConvertor = new QsprConvertor();
			string text = Path.Combine(DestinationDirectory, qsprConvertor.GetFormattedXmlName(qsprLogFilePath));
			if (File.Exists(text))
			{
				ErrorMessage = "Target file \"" + text + "\" already exists";
				base.Env.DebugMessage.Write("Temp", ErrorMessage);
				return false;
			}
			if (DeleteOriginal)
			{
				File.Move(qsprLogFilePath, text);
			}
			else
			{
				File.Copy(qsprLogFilePath, text);
			}
			base.Env.DebugMessage.Write("Temp", "Success: \"" + text + "\"");
			return true;
		}
		catch (Exception ex)
		{
			base.Env.DebugMessage.Write("Temp", ex.ToString());
			ErrorMessage = ex.ToString();
			return false;
		}
	}

	private void RemoveExtraCsvColumns(DataTable dt)
	{
		string[] array = new string[18]
		{
			"Link", "ArrayUpperLimit", "ArrayResult", "ArrayParamIndex", "ArrayParamCharResult", "ArrayLowerLimit", "SessionDataRID", "MCN", "TreeID", "TesterID",
			"LastVisit", "RunTitle", "PassFail", "ScnValue", "VisitNum", "WorkStation", "GlobalResult", "DvtFlag"
		};
		if (dt == null || dt.Rows.Count <= 0)
		{
			return;
		}
		string[] array2 = array;
		foreach (string name in array2)
		{
			if (dt.Columns.Contains(name))
			{
				dt.Columns.Remove(name);
			}
		}
	}

	private string JoinDataWithDelimiter(object[] objectValues, string delimiter)
	{
		string[] array = new string[objectValues.Length];
		for (int i = 0; i < objectValues.Length; i++)
		{
			array[i] = GetCsvFormattedString(objectValues[i].ToString());
		}
		return string.Join(delimiter, array);
	}

	private string GetCsvFormattedString(string inputString)
	{
		if (inputString.Contains("\""))
		{
			inputString = inputString.Replace("\"", "\"\"");
		}
		if (inputString.Contains(",") || inputString.Contains(Environment.NewLine) || inputString.Contains("\""))
		{
			inputString = "\"" + inputString + "\"";
		}
		return inputString;
	}
}
