using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using QC.QTMDotNetKernelInterface;
using QC.QTMDotNetKernelInterface.Environment;

namespace QC.QTMToolKit.Tools;

[QTMTestClass]
public class CSVFileHandler : QSPRTest
{
	private string[] csvAllRows;

	private int currRow;

	private string csvFileName;

	private string errorMsg;

	[QTMParameter(ParameterIOType.Input, TestList = "OpenCSVFile,GetRowColIndex,GetCellValueUsingColumnName,GetCellValue,GetCellValueFromKey", DisplayHint = DisplayHints.FILE, Description = "Name of the CSV file.")]
	public string CSVFileName
	{
		get
		{
			return csvFileName;
		}
		set
		{
			csvFileName = value;
		}
	}

	[QTMParameter(ParameterIOType.Output, TestList = "OpenCSVFile,GetNextRowData,GetRowColIndex,GetCellValueUsingColumnName,GetCellValue,GetCellValueFromKey")]
	public string ErrorMsg
	{
		get
		{
			return errorMsg;
		}
		set
		{
			errorMsg = value;
		}
	}

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

	[QTMTest(Description = "Opens a CSVFile and keeps the contents available for furhter reading from other tests", CanAddToTestPlan = true)]
	public bool OpenCSVFile(bool skipHeader)
	{
		errorMsg = "";
		try
		{
			csvAllRows = File.ReadAllLines(csvFileName);
			currRow = 0;
			if (skipHeader)
			{
				currRow = 1;
			}
			return true;
		}
		catch (Exception ex)
		{
			errorMsg = ex.Message;
			return false;
		}
	}

	[QTMTest(Description = "Reads the data from Start to EndCol as a string. Call OpenCSVFile test first. Also returns a bool that indicates if there is more data or not. Col and Row index starts with 0", CanAddToTestPlan = true)]
	public bool GetNextRowData(int startCol, int endCol, bool gotoNextRow, out string data, out bool nextRowAvilable)
	{
		data = "";
		errorMsg = "";
		nextRowAvilable = false;
		try
		{
			if (csvAllRows == null)
			{
				errorMsg = "Make sure there is a CSV file open using OpenCSVFile test";
				return false;
			}
			if (csvAllRows.GetLength(0) > currRow)
			{
				string[] array = SplitCSVWithQuotes(csvAllRows[currRow]);
				if (gotoNextRow)
				{
					currRow++;
				}
				int num = startCol;
				while (array.Length > num)
				{
					data = data + array[num++] + ",";
					if (num > endCol)
					{
						break;
					}
				}
				if (data.EndsWith(","))
				{
					data = data.Remove(data.LastIndexOf(','));
				}
				if (csvAllRows.GetLength(0) > currRow)
				{
					nextRowAvilable = true;
				}
			}
			else
			{
				errorMsg = "Data not available for the given row.";
			}
			return true;
		}
		catch (Exception ex)
		{
			errorMsg = ex.Message;
			return false;
		}
	}

	[QTMTest(Description = "Creates a CSVfile based on the input Data Table", CanAddToTestPlan = true)]
	public bool CreateACSVFile(DataTable dataTable, string csvFileName, bool includeColNames)
	{
		if (dataTable == null)
		{
			return false;
		}
		try
		{
			base.Env.DebugMessage.Write("CreateCSVFile", " Column count " + dataTable.Columns.Count);
			StreamWriter streamWriter = File.CreateText(csvFileName);
			int count = dataTable.Columns.Count;
			if (includeColNames)
			{
				for (int i = 0; i < count - 1; i++)
				{
					streamWriter.Write(dataTable.Columns[i].ColumnName + ",");
				}
				streamWriter.Write(dataTable.Columns[count - 1].ColumnName + "\r\n");
			}
			foreach (DataRow row in dataTable.Rows)
			{
				string text;
				for (int j = 0; j < count - 1; j++)
				{
					text = row[j].ToString();
					if (text.Contains(","))
					{
						text = "\"" + text + "\"";
					}
					streamWriter.Write(text + ",");
				}
				text = row[count - 1].ToString();
				if (text.Contains(","))
				{
					text = "\"" + text + "\"";
				}
				streamWriter.Write(text + "\r\n");
			}
			streamWriter.Flush();
			streamWriter.Close();
		}
		catch (Exception ex)
		{
			base.Env.DebugMessage.Write("CreateCSVFile", ex.Message);
			return false;
		}
		return true;
	}

	[QTMParameter(ArgumentName = "CommaSepString", Description = "The comma separate string to append as a new row")]
	[QTMParameter(ArgumentName = "CsvFileName", Description = "The name of the CSV file to append the row to")]
	[QTMTest(Description = "Appends a comma separated string as a new row in the specified CSV filename.", CanAddToTestPlan = true)]
	public bool AppendCsvRow(string CommaSepString, string CsvFileName)
	{
		try
		{
			if (!File.Exists(CsvFileName))
			{
				base.Env.DebugMessage.Write("Error", "Failed to append Csv row, the file does not exist: " + CsvFileName);
				return false;
			}
			string text = File.ReadAllText(CsvFileName);
			string text2 = CommaSepString + Environment.NewLine;
			if (!text.EndsWith(Environment.NewLine))
			{
				text2 = Environment.NewLine + text2;
			}
			File.AppendAllText(CsvFileName, text2);
		}
		catch (Exception ex)
		{
			base.Env.DebugMessage.Write("AppendCsvRow", ex.Message);
			return false;
		}
		return true;
	}

	[QTMTest(Description = "Returns Row and column index (0 based index) from a CSV file based on Column Name and Row value", CanAddToTestPlan = true)]
	public bool GetRowColIndex(string csvColumnName, string csvRowValue, out int csvRowNo, out int csvColNo)
	{
		csvRowNo = (csvColNo = -9999);
		errorMsg = "";
		try
		{
			csvColumnName = csvColumnName.Trim();
			csvRowValue = csvRowValue.Trim();
			string[] array = File.ReadAllLines(csvFileName);
			string[] array2 = SplitCSVWithQuotes(array[0]);
			int num = 0;
			for (num = 0; num < array2.Length && !(array2[num] == csvColumnName); num++)
			{
			}
			if (num >= array2.Length)
			{
				errorMsg = "Column header " + csvColumnName + " not found";
				return false;
			}
			csvColNo = num;
			int num2 = 0;
			for (num2 = 1; num2 < array.Length; num2++)
			{
				string rowData = array[num2];
				string[] array3 = SplitCSVWithQuotes(rowData);
				if (array3.Length >= csvColNo && array3[csvColNo] == csvRowValue)
				{
					break;
				}
			}
			if (num2 >= array.Length)
			{
				errorMsg = csvRowValue + " not found at column " + csvColNo;
				return false;
			}
			csvRowNo = num2;
		}
		catch (Exception ex)
		{
			errorMsg = ex.Message;
			return false;
		}
		return true;
	}

	[QTMTest(Description = "Returns cell value from a CSV file based on Column name and row number (0 based index)", CanAddToTestPlan = true)]
	public bool GetCellValueUsingColumnName(string csvColumnName, int csvRowNo, out string csvCellValue)
	{
		csvCellValue = "";
		errorMsg = "";
		try
		{
			csvColumnName = csvColumnName.Trim();
			string[] array = File.ReadAllLines(csvFileName);
			string[] array2 = SplitCSVWithQuotes(array[0]);
			int num = 0;
			for (num = 0; num < array2.Length && !(array2[num] == csvColumnName); num++)
			{
			}
			if (num >= array2.Length)
			{
				errorMsg = "Column header " + csvColumnName + " not found";
				return false;
			}
			return GetCellValueFromStringArray(array, num, csvRowNo, out csvCellValue);
		}
		catch (Exception ex)
		{
			base.Env.DebugMessage.Write("GetCellValueFromHeaderFromCSVFile", ex.Message);
			errorMsg = ex.Message;
			return false;
		}
	}

	[QTMTest(Description = "Returns the cell value from a CSV file based on the Column and Row index (0 based index)", CanAddToTestPlan = true)]
	public bool GetCellValue(int csvColNo, int csvRowNo, out string csvCellValue)
	{
		csvCellValue = "";
		errorMsg = "";
		try
		{
			string[] rows = File.ReadAllLines(csvFileName);
			return GetCellValueFromStringArray(rows, csvColNo, csvRowNo, out csvCellValue);
		}
		catch (Exception ex)
		{
			errorMsg = ex.Message;
			return false;
		}
	}

	private bool GetCellValueFromStringArray(string[] rows, int colNo, int rowNo, out string cellValue)
	{
		cellValue = "";
		errorMsg = "";
		try
		{
			if (rows.Length < rowNo)
			{
				errorMsg = "Row " + rowNo + " not found ";
				return false;
			}
			string[] array = SplitCSVWithQuotes(rows[rowNo]);
			if (array.Length <= colNo)
			{
				errorMsg = "Column " + colNo + " not found ";
				return false;
			}
			cellValue = array[colNo];
		}
		catch (Exception ex)
		{
			errorMsg = ex.Message;
			return false;
		}
		return true;
	}

	[QTMTest(Description = "For the given Column name, the function finds the row in which the key value is present. For the same row, finds the column in which the ValueColumnName is found and gets the cell value.", CanAddToTestPlan = true)]
	public bool GetCellValueFromKey(string csvKeyColumnName, string csvKeyValue, string csvValueColumnName, out string cellValue)
	{
		cellValue = "";
		errorMsg = "";
		if (GetRowColIndex(csvKeyColumnName, csvKeyValue, out var csvRowNo, out var _) && GetCellValueUsingColumnName(csvValueColumnName, csvRowNo, out cellValue))
		{
			return true;
		}
		return false;
	}

	[QTMTest(CanAddToTestPlan = true)]
	public string[] SplitCSVWithQuotes(string rowData)
	{
		Regex regex = new Regex("\"[^\"\\r\\n]*\"|'[^'\\r\\n]*'|[^,\\r\\n]*");
		Match match = regex.Match(rowData);
		ArrayList arrayList = new ArrayList();
		string text = "'\"";
		while (match.Success)
		{
			if (match.Value != string.Empty)
			{
				arrayList.Add(match.Value.Trim(text.ToCharArray()));
			}
			match = match.NextMatch();
		}
		string[] array = new string[arrayList.Count];
		for (int i = 0; i < arrayList.Count; i++)
		{
			array[i] = arrayList[i].ToString();
		}
		return array;
	}
}
