using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml.Serialization;
using QC.QSPR;
using QC.QsprShared.Dialogs;
using QC.QsprShared.Trace;
using QC.QsprShared.Utilities;
using QC.QsprTestObjects.Parameters;
using QC.QsprTestObjects.Tests.Base;
using QC.QTMInterface;

namespace QC.QsprTestObjects.Loops;

public class LoopCondition : ISerializable
{
	internal const int MAX_NO_LIST_ENTRY = 20000;

	internal const string EXCEED_MAX = "LoopExceedMax";

	public const string NOT_2D_ARRAY = "";

	private const int NOT_ARRAY_PARAMETER = -2;

	private const int LOOP_ON_ALL_INDEX = -1;

	public const string LOOP_DETAILS_SEP = "@#$%";

	public const int FILE_TYPE_INDEX = 0;

	public const int FILE_NAME_INDEX = 1;

	public const int COLUMN_NAME_INDEX = 2;

	public const int FILE_NAME_FROM_GV_INDEX = 3;

	public const int LOOP_COUNT_FROM_GV_INDEX = 0;

	public const int LOOP_COUNT_GV_INDEX = 1;

	public const int LOOP_TIME_TYPE_INDEX = 0;

	public const int LOOP_TIME_FROM_GV_INDEX = 1;

	public const int LOOP_TIME_GV_INDEX = 2;

	private string name;

	private string testName;

	private string paramName;

	private LoopOnTypes loopOnType = LoopOnTypes.INPUTPARAM;

	private ArrayList ListOfValues = new ArrayList();

	private string strOrigValue;

	private LoopTypes loopType;

	private string DontRunCond;

	private string testIndex;

	private int arrayIndex = -2;

	private string array2DIndex = "";

	private DataType dataType = DataType.String;

	private long scenarioID = -1L;

	private string loopDetails = "";

	private bool isNullable;

	private bool ignoreIntermediateResults;

	[DefaultValue("")]
	public string LoopDetails
	{
		get
		{
			return loopDetails;
		}
		set
		{
			loopDetails = value;
		}
	}

	public string LoopName
	{
		get
		{
			return name;
		}
		set
		{
			string newStr = name;
			QTMUtility.RemoveSpecialCharacter(value, out newStr);
			name = newStr.Trim();
		}
	}

	public string TestName
	{
		get
		{
			return testName;
		}
		set
		{
			testName = value;
		}
	}

	public string ParamName
	{
		get
		{
			return paramName;
		}
		set
		{
			paramName = value;
		}
	}

	public DataType DataType
	{
		get
		{
			return dataType;
		}
		set
		{
			dataType = value;
		}
	}

	[DefaultValue(false)]
	public bool IsNullable
	{
		get
		{
			return isNullable;
		}
		set
		{
			isNullable = value;
		}
	}

	public LoopTypes LoopType
	{
		get
		{
			return loopType;
		}
		set
		{
			loopType = value;
			if (strOrigValue != null)
			{
				OriginalValue = strOrigValue;
			}
		}
	}

	public LoopOnTypes LoopOnType
	{
		get
		{
			return loopOnType;
		}
		set
		{
			loopOnType = value;
		}
	}

	[XmlIgnore]
	public ArrayList LoopValues
	{
		get
		{
			return ListOfValues;
		}
		set
		{
			ListOfValues = value;
		}
	}

	public string LoopValuesAsString
	{
		get
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (LoopValues.Count > 0 && LoopValues.Count < 20000)
			{
				for (int i = 0; i < LoopValues.Count - 1; i++)
				{
					stringBuilder.Append(LoopValues[i]);
					stringBuilder.Append(",");
				}
				stringBuilder.Append(LoopValues[LoopValues.Count - 1]);
			}
			else if (LoopValues.Count > 20000 && LoopType == LoopTypes.STARTSTOPSTEP)
			{
				stringBuilder.Append("LoopExceedMax:" + OriginalValue);
			}
			return stringBuilder.ToString();
		}
		set
		{
			try
			{
				if (value.Contains("LoopExceedMax") && LoopType == LoopTypes.STARTSTOPSTEP)
				{
					string loopValuesForSSS = value.Replace("LoopExceedMax:", "");
					SetLoopValuesForSSS(loopValuesForSSS);
					return;
				}
				string[] array = value.Split(',');
				LoopValues.Clear();
				string[] array2 = array;
				foreach (string value2 in array2)
				{
					LoopValues.Add(value2);
				}
			}
			catch (Exception ex)
			{
				TraceMessage.Write(ToString(), "LoopValuesAsString " + ex.ToString(), TraceMessageType.Exception);
			}
		}
	}

	public int ArrayIndex
	{
		get
		{
			return arrayIndex;
		}
		set
		{
			arrayIndex = value;
		}
	}

	public string Array2DIndex
	{
		get
		{
			return array2DIndex;
		}
		set
		{
			array2DIndex = value;
		}
	}

	public long ScenarioID
	{
		get
		{
			return (int)scenarioID;
		}
		set
		{
			scenarioID = (int)value;
		}
	}

	public string DontRunCondition
	{
		get
		{
			return DontRunCond;
		}
		set
		{
			DontRunCond = value;
		}
	}

	public string TestIndex
	{
		get
		{
			return testIndex;
		}
		set
		{
			testIndex = value;
		}
	}

	[DefaultValue(false)]
	public bool IgnoreIntermediateResults
	{
		get
		{
			return ignoreIntermediateResults;
		}
		set
		{
			ignoreIntermediateResults = value;
		}
	}

	public string OriginalValue
	{
		get
		{
			return strOrigValue;
		}
		set
		{
			switch (loopType)
			{
			case LoopTypes.STARTSTOPSTEP:
			{
				string strResult = "";
				try
				{
					if (CalculateListOfValues(value, out var Result, out strResult, out var iNumElts))
					{
						LoopValues.Clear();
						for (int j = 0; j < iNumElts; j++)
						{
							LoopValues.Add(Result[j]);
						}
						strOrigValue = value;
						break;
					}
					throw new Exception("Loop value is invalid");
				}
				catch (Exception ex4)
				{
					throw new Exception(ex4.Message);
				}
			}
			case LoopTypes.LIST:
				try
				{
					LoopValues.Clear();
					string[] array = value.Split(',');
					string[] array2 = array;
					foreach (string value2 in array2)
					{
						LoopValues.Add(value2);
					}
					strOrigValue = value;
					break;
				}
				catch (Exception ex3)
				{
					TraceMessage.Write(ToString(), "OriginalValue " + ex3.Message, TraceMessageType.Exception);
					AppMessageDialog.Show("Error Calcuating List values", "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
					break;
				}
			case LoopTypes.BYCOUNT:
				try
				{
					LoopValues.Clear();
					LoopValues.Add(value);
					strOrigValue = value;
					break;
				}
				catch (Exception ex2)
				{
					TraceMessage.Write(ToString(), "OriginalValue " + ex2.Message, TraceMessageType.Exception);
					AppMessageDialog.Show("Error in Count Value", "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
					break;
				}
			case LoopTypes.BYTIME:
				try
				{
					LoopValues.Clear();
					LoopValues.Add(value);
					strOrigValue = value;
					break;
				}
				catch (Exception ex)
				{
					TraceMessage.Write(ToString(), "OriginalValue " + ex.Message, TraceMessageType.Exception);
					AppMessageDialog.Show("Error in Count Value", "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
					break;
				}
			}
		}
	}

	public LoopCondition Clone()
	{
		try
		{
			LoopCondition loopCondition = new LoopCondition();
			loopCondition.LoopValues = (ArrayList)LoopValues.Clone();
			loopCondition.LoopOnType = LoopOnType;
			loopCondition.LoopType = LoopType;
			loopCondition.name = name;
			loopCondition.strOrigValue = strOrigValue;
			loopCondition.ParamName = ParamName;
			loopCondition.TestName = TestName;
			loopCondition.TestIndex = TestIndex;
			loopCondition.arrayIndex = arrayIndex;
			loopCondition.array2DIndex = array2DIndex;
			loopCondition.dataType = dataType;
			loopCondition.isNullable = isNullable;
			loopCondition.scenarioID = scenarioID;
			loopCondition.LoopDetails = LoopDetails;
			loopCondition.IgnoreIntermediateResults = ignoreIntermediateResults;
			return loopCondition;
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "Clone " + ex.Message, TraceMessageType.Exception);
		}
		return null;
	}

	public bool UpdateLoopValues(RootTest root, out string errorMessage, string TreeName)
	{
		bool result = true;
		errorMessage = "";
		try
		{
			if (LoopType == LoopTypes.LIST)
			{
				if (LoopDetails.Trim().Length > 0)
				{
					string[] array = loopDetails.Split(new string[1] { "@#$%" }, StringSplitOptions.None);
					string delimiterString = array[0];
					string text = array[1];
					string columnName = array[2];
					if (array.Length > 3)
					{
						string strA = array[3];
						if (string.Compare(strA, "True") == 0)
						{
							if (!root.Scheduler.Env.GlobalVariable.GetGlobalVariable(text.Trim(), out var gvValue) || string.IsNullOrEmpty(gvValue) || !File.Exists(gvValue))
							{
								errorMessage = $"Global Variable: {text.Trim()} used for the CSV file name doesn't exist or the value is invalid.  \nPlease add or update this global variable with a valid CSV file name.";
								return false;
							}
							text = gvValue;
						}
					}
					string strValues = "";
					if (!GetLoopValuesFromFile(text, TreeName, columnName, delimiterString, out strValues, out errorMessage))
					{
						return false;
					}
					strOrigValue = strValues;
					LoopValuesAsString = strValues;
				}
			}
			else if (loopType == LoopTypes.BYCOUNT)
			{
				if (LoopDetails.Trim().Length > 0)
				{
					string[] array2 = loopDetails.Split(new string[1] { "@#$%" }, StringSplitOptions.None);
					string strA2 = array2[0];
					int result2 = 0;
					if (string.Compare(strA2, "True") == 0)
					{
						string text2 = array2[1];
						if (!root.Scheduler.Env.GlobalVariable.GetGlobalVariable(text2, out var gvValue2) || string.IsNullOrEmpty(gvValue2) || !int.TryParse(gvValue2, out result2) || result2 < 0)
						{
							errorMessage = $"Global Variable: {text2} used for the loop count doesn't exist or the value is invalid.  \nPlease add or update this global variable with a valid loop count.";
							return false;
						}
					}
					strOrigValue = result2.ToString();
				}
			}
			else if (loopType == LoopTypes.BYTIME && LoopDetails.Trim().Length > 0)
			{
				string[] array3 = loopDetails.Split(new string[1] { "@#$%" }, StringSplitOptions.None);
				if (array3.Length > 1)
				{
					string strA3 = array3[1];
					int result3 = 0;
					if (string.Compare(strA3, "True") == 0)
					{
						string text3 = array3[2];
						if (!root.Scheduler.Env.GlobalVariable.GetGlobalVariable(text3, out var gvValue3) || string.IsNullOrEmpty(gvValue3) || !int.TryParse(gvValue3, out result3) || result3 < 0)
						{
							errorMessage = $"Global Variable: {text3} used for the time value doesn't exist or the value is invalid.  \nPlease add or update this global variable with a valid time.";
							return false;
						}
					}
					strOrigValue = result3.ToString();
				}
			}
		}
		catch
		{
		}
		return result;
	}

	public static bool GetLoopValuesFromFile(string fileName, string TreeName, string columnName, string delimiterString, out string strValues, out string errorMessage)
	{
		strValues = "";
		errorMessage = "";
		try
		{
			char c = ',';
			if (delimiterString == "Tab")
			{
				c = '\t';
			}
			ArrayList rowsFromFile = GetRowsFromFile(fileName, TreeName);
			string[] array = ((string)rowsFromFile[0]).Split(c);
			int num = -1;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i].Trim() == columnName.Trim())
				{
					num = i;
				}
			}
			if (num == -1)
			{
				errorMessage = "Column " + columnName + " not found in the file.";
				return false;
			}
			for (int j = 1; j < rowsFromFile.Count; j++)
			{
				string[] array2 = ((string)rowsFromFile[j]).Split(c);
				try
				{
					if (j == 1)
					{
						strValues = array2[num];
					}
					else
					{
						strValues = strValues + "," + array2[num];
					}
				}
				catch
				{
					strValues += ",";
				}
			}
			return true;
		}
		catch (Exception ex)
		{
			errorMessage += ex.Message;
			return false;
		}
	}

	public static ArrayList GetRowsFromFile(string filename, string TreeName)
	{
		ArrayList arrayList = new ArrayList();
		filename = PathUtils.ConvertToAbsolute(TreeName, filename);
		using FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
		using StreamReader streamReader = new StreamReader(stream);
		string text;
		while ((text = streamReader.ReadLine()) != null)
		{
			if (text.Trim().Length > 0)
			{
				arrayList.Add(text);
			}
		}
		return arrayList;
	}

	public string GetDisplayString(RootTest root, string loopString)
	{
		StringBuilder stringBuilder = new StringBuilder();
		try
		{
			if (loopType != LoopTypes.BYSEQUENCE)
			{
				string loopValueFinalAsString = GetLoopValueFinalAsString(root, LoopValues, TestIndex, ParamName, OriginalValue);
				if (loopValueFinalAsString != LoopValuesAsString)
				{
					List<string> list = LoopValuesAsString.Split(',').ToList();
					List<string> list2 = loopValueFinalAsString.Split(',').ToList();
					int num = list.IndexOf(loopString);
					if (num > -1 && list2.Count > num)
					{
						return $"{loopString} {list2[num]}";
					}
					return loopString;
				}
				return loopString;
			}
			string[] array = testName.Split(new string[1] { "_;_" }, StringSplitOptions.None);
			string[] array2 = loopString.Split('_');
			for (int i = 0; i < array2.Length; i++)
			{
				if (i == array2.Length - 1)
				{
					stringBuilder.Append($"{array[int.Parse(array2[i])]}");
				}
				else
				{
					stringBuilder.Append(string.Format("{0}{1}", array[int.Parse(array2[i])], "_;_"));
				}
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "GetDisplayString " + ex.ToString(), TraceMessageType.Exception);
			return loopString;
		}
		return stringBuilder.ToString();
	}

	public List<string> GetDisplayStrings(RootTest root, ArrayList loopValues, string testIndex, string parameterName, string originalVal)
	{
		List<string> list = new List<string>();
		BaseTest baseTest = root.FindTest(testIndex);
		ParameterCls parameterCls = null;
		if (baseTest != null)
		{
			parameterCls = baseTest.Properties.Parameters.GetParameter(parameterName);
		}
		if (loopValues.Count > 0 && loopValues.Count < 20000)
		{
			for (int i = 0; i < loopValues.Count; i++)
			{
				if (baseTest != null && parameterCls != null)
				{
					list.Add(parameterCls.GetDisplayValue(loopValues[i].ToString()));
				}
				else
				{
					list.Add(loopValues[i].ToString());
				}
			}
		}
		else if (loopValues.Count > 20000)
		{
			list.Add("LoopExceedMax:" + originalVal);
		}
		return list;
	}

	private static string GetLoopValueFinalAsString(RootTest root, ArrayList loopValues, string testIndex, string parameterName, string originalVal)
	{
		BaseTest baseTest = root.FindTest(testIndex);
		ParameterCls parameterCls = null;
		if (baseTest != null)
		{
			parameterCls = baseTest.Properties.Parameters.GetParameter(parameterName);
		}
		StringBuilder stringBuilder = new StringBuilder();
		if (loopValues.Count > 0 && loopValues.Count < 20000)
		{
			string text = "";
			for (int i = 0; i < loopValues.Count - 1; i++)
			{
				if (baseTest != null)
				{
					text = ((parameterCls == null) ? loopValues[i].ToString() : parameterCls.GetDisplayValue(loopValues[i].ToString()));
					stringBuilder.Append(text);
					stringBuilder.Append(",");
				}
				else
				{
					stringBuilder.Append(loopValues[i]);
					stringBuilder.Append(",");
				}
			}
			if (baseTest != null)
			{
				text = ((parameterCls == null) ? loopValues[loopValues.Count - 1].ToString() : parameterCls.GetDisplayValue(loopValues[loopValues.Count - 1].ToString()));
				stringBuilder.Append(text);
			}
			else
			{
				stringBuilder.Append(loopValues[loopValues.Count - 1]);
			}
		}
		else if (loopValues.Count > 20000)
		{
			stringBuilder.Append("LoopExceedMax:" + originalVal);
		}
		return stringBuilder.ToString();
	}

	private void SetLoopValuesForSSS(string loopValueString)
	{
		string strResult = "";
		try
		{
			if (CalculateListOfValues(loopValueString, out var Result, out strResult, out var iNumElts))
			{
				LoopValues.Clear();
				for (int i = 0; i < iNumElts; i++)
				{
					LoopValues.Add(Result[i]);
				}
				return;
			}
			throw new Exception("Loop value for SSS is invalid");
		}
		catch (Exception ex)
		{
			throw new Exception(ex.Message);
		}
	}

	public static string ParseSSSValue(string loopValue, out LoopTypes assignedLoopType)
	{
		assignedLoopType = LoopTypes.LIST;
		try
		{
			loopValue = loopValue.ToUpper().Replace(" ", "");
			Regex regex = new Regex("SSS\\([-+]?[0-9]*\\.?[0-9]+,[-+]?[0-9]*\\.?[0-9]+,[-+]?[0-9]*\\.?[0-9]+\\)");
			MatchCollection matchCollection = regex.Matches(loopValue);
			if (matchCollection.Count == 1 && matchCollection[0].ToString() == loopValue)
			{
				assignedLoopType = LoopTypes.STARTSTOPSTEP;
				return matchCollection[0].ToString().Replace("SSS(", "").Replace(")", "");
			}
			for (int i = 0; i < matchCollection.Count; i++)
			{
				Match match = matchCollection[i];
				string text = match.ToString();
				string strValue = text.Replace("SSS(", "").Replace(")", "");
				if (CalculateListOfValues(strValue, out var _, out var strResult, out var _))
				{
					loopValue = loopValue.Replace(text, strResult);
					continue;
				}
				throw new Exception("SSS is invalid.  Correct form SSS(1,20,1)");
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write("LoopCondition.cs ParseSSSValue ", ex.Message, TraceMessageType.Exception);
		}
		return loopValue;
	}

	public static bool CalculateListOfValues(string strValue, out string[] Result, out string strResult, out int iNumElts)
	{
		List<string> list = new List<string>();
		iNumElts = 0;
		Result = null;
		strResult = "";
		try
		{
			string[] array = strValue.Split(',');
			double num = double.Parse(array[0], CultureInfo.InvariantCulture);
			double num2 = double.Parse(array[1], CultureInfo.InvariantCulture);
			double num3 = double.Parse(array[2], CultureInfo.InvariantCulture);
			if (num3 == 0.0)
			{
				AppMessageDialog.Show("Step Cannot be Zero(0)", "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Warning);
				return false;
			}
			if (num3 > 0.0 && num > num2)
			{
				num3 = 0.0 - num3;
			}
			if (num3 < 0.0 && num2 > num)
			{
				num3 = 0.0 - num3;
			}
			for (double num4 = num; (num3 > 0.0) ? (num4 <= num2) : (num4 >= num2); num4 += num3)
			{
				list.Add(num4.ToString());
			}
			Result = list.ToArray();
			strResult = string.Join(",", list.ToArray());
			iNumElts = list.Count;
			return true;
		}
		catch (Exception ex)
		{
			TraceMessage.Write("LoopCondition", "CalculateListOfValues " + ex.Message, TraceMessageType.Exception);
			return false;
		}
	}

	public void GetObjectData(SerializationInfo info, StreamingContext context)
	{
	}
}
