using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Xml.Serialization;
using QC.QTMInterface;

namespace QC.QSPRAutomation.Internal;

internal class QSPRInstance
{
	public delegate void AppendToLocalLogDelegate(string instanceIdentifer, string message);

	public delegate void ProcessReceivedQSPRMessageDelegate(string instanceIdentifer, MsgData msgData);

	public delegate void ProcessReceivedQSPRDebugMessageDelegate(string instanceIdentifer, string windowName, string text, int traceLevel);

	public delegate void ProcessGlobalVariablesModifiedDelegate(string instanceIdentifer, string gvName, string gvValue);

	public delegate void QSPRExitedDelegate(string instanceIdentifer, int exitCode);

	public delegate void QSPRStartedDelegate();

	public delegate void QSPRShownDelegate(bool shownOkay);

	public delegate void QSPRHiddenDelegate(bool hiddenOkay);

	private enum WindowShowStyle
	{
		Hide,
		ShowNormal,
		ShowMinimized,
		Maximize,
		ShowNormalNoActivate,
		Show,
		Minimize,
		ShowMinNoActivate,
		ShowNoActivate,
		Restore,
		ShowDefault,
		ForceMinimized
	}

	private QSPR2Compatability qspr2Compatibility;

	private bool portMisMatch;

	private string messageArgSeparator = "_$_";

	public AppendToLocalLogDelegate appendToLocalLogDelegate;

	public ProcessReceivedQSPRMessageDelegate processReceivedQSPRMessageDelegate;

	public ProcessReceivedQSPRDebugMessageDelegate processReceivedQSPRDebugMessageDelegate;

	public ProcessGlobalVariablesModifiedDelegate processGlobalVariablesModifiedDelegate;

	public QSPRExitedDelegate qsprExitedDelegate;

	public QSPRStartedDelegate qsprStartedDelegate;

	public QSPRShownDelegate qsprShownDelegate;

	public QSPRHiddenDelegate qsprHiddenDelegate;

	private string SEND_QSPR_DEBUG_MESSAGES = "SEND_QSPR_DEBUG_MESSAGES";

	private Process qsprProcess;

	private RemoteableObject qsprAutomation;

	private string qsprExecutablePath = "C:\\work\\Tools\\QSPR\\Output\\Bin\\qspr.exe";

	private string qsprAdditionalCommandLineParameters = "";

	private int portNumber;

	private string instanceIdentifier;

	private string initialTestTreeName;

	private int connectTries = 10;

	private int connectDelayMs = 3000;

	private bool enableQspr2Compatibility;

	private Position folderInsertPosition = Position.Last;

	private bool removeRootFolder = true;

	public Action<long> TestPlanLoadComplete { get; set; }

	public TestMessageReceivedDelegate TestMessageReceived { get; set; }

	public string QSPRExecutablePath
	{
		get
		{
			return qsprExecutablePath;
		}
		set
		{
			qsprExecutablePath = value;
		}
	}

	public string QSPRAdditionalCommandLineParameters
	{
		get
		{
			return qsprAdditionalCommandLineParameters;
		}
		set
		{
			qsprAdditionalCommandLineParameters = value;
		}
	}

	public int PortNumber
	{
		get
		{
			return portNumber;
		}
		set
		{
			portNumber = value;
		}
	}

	public string InstanceIdentifier
	{
		get
		{
			return instanceIdentifier;
		}
		set
		{
			instanceIdentifier = value;
		}
	}

	public string InitialTestTreeName
	{
		get
		{
			return initialTestTreeName;
		}
		set
		{
			initialTestTreeName = value;
		}
	}

	public int ConnectTries
	{
		get
		{
			return connectTries;
		}
		set
		{
			connectTries = value;
		}
	}

	public int ConnectDelayMs
	{
		get
		{
			return connectDelayMs;
		}
		set
		{
			connectDelayMs = value;
		}
	}

	public bool EnableQspr2Compatibility
	{
		get
		{
			return enableQspr2Compatibility;
		}
		set
		{
			enableQspr2Compatibility = value;
			if (enableQspr2Compatibility)
			{
				qspr2Compatibility = new QSPR2Compatability();
			}
		}
	}

	public bool IsQsprInstanceAlive
	{
		get
		{
			if (qsprProcess != null && !qsprProcess.HasExited)
			{
				return true;
			}
			return false;
		}
	}

	public bool CloseHidesUI
	{
		get
		{
			object obj = SendSpecialMessageToQSPRAndReceiveData("Get Close Hides UI", "");
			string value = obj as string;
			return bool.Parse(value);
		}
		set
		{
			string additionalInformation = value.ToString();
			SendSpecialMessageToQSPR("Set Close Hides UI", additionalInformation);
		}
	}

	private void InitializeQSPR()
	{
		SuppressResultsDialog(supress: true);
		SuppressSerialNumberDialog(supress: true);
		SuppressAllMessages(supress: true);
	}

	public int GetQsprProcessID()
	{
		if (IsQsprInstanceAlive)
		{
			return qsprProcess.Id;
		}
		return -1;
	}

	public bool VerifyProcessPort(int port, out bool processMatched)
	{
		processMatched = true;
		try
		{
			string text = "0";
			if ((text = qsprAutomation.Ping("PID")) == qsprProcess.Id.ToString())
			{
				return true;
			}
			processMatched = false;
			AppendToLocalLog("VerifyProcessPort() failed - Process id did not match: PID=" + text);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("VerifyProcessPort() failed - " + ex.Message);
		}
		return false;
	}

	public bool StartQSPR(bool hidden)
	{
		try
		{
			if (VerifyProcess())
			{
				if (VerifyConnection())
				{
					AppendToLocalLog("StartQSPR() okay: already connected");
					return true;
				}
				qsprProcess.Kill();
				if (portMisMatch)
				{
					AppendToLocalLog("StartQSPR() Failed: the port is being used by another process");
					portMisMatch = false;
					return false;
				}
			}
			if (!StartProcess())
			{
				AppendToLocalLog("StartQSPR() failed: StartProcess() failed");
				return false;
			}
			if (!ConnectToServer(connectTries, connectDelayMs))
			{
				AppendToLocalLog("StartQSPR() failed: ConnectToServer(" + connectTries + ", " + connectDelayMs + ") failed");
				qsprProcess.Kill();
				return false;
			}
			InitializeQSPR();
			if (hidden)
			{
				HideWindow();
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("StartQSPR() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("StartQSPR() okay");
		return true;
	}

	public bool StartQSPR(bool hidden, bool withoutTestTree, string backgroundColor)
	{
		AppendToLocalLog("In Start QSPR method");
		if (!withoutTestTree)
		{
			return StartQSPR(hidden);
		}
		try
		{
			if (VerifyProcess())
			{
				if (VerifyConnection())
				{
					AppendToLocalLog("StartQSPR() okay: already connected");
					return true;
				}
				AppendToLocalLog("Killing QSPR process");
				if (qsprProcess == null)
				{
					AppendToLocalLog("QSPR process is null");
				}
				qsprProcess.Kill();
				if (portMisMatch)
				{
					portMisMatch = false;
					return false;
				}
			}
			if (!StartProcessWithDefaultArgs(hidden, backgroundColor))
			{
				AppendToLocalLog("StartQSPR() failed: StartProcess() failed");
				return false;
			}
			if (!ConnectToServer(connectTries, connectDelayMs))
			{
				AppendToLocalLog("StartQSPR() failed: ConnectToServer(" + connectTries + ", " + connectDelayMs + ") failed");
				AppendToLocalLog("Killing QSPR process with process ID = " + qsprProcess.Id);
				qsprProcess.Kill();
				return false;
			}
			AppendToLocalLog("Initializing QSPR");
			InitializeQSPR();
		}
		catch (Exception ex)
		{
			AppendToLocalLog("StartQSPR() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("StartQSPR() okay");
		return true;
	}

	public bool KillQSPR()
	{
		try
		{
			qsprProcess.Kill();
		}
		catch (Exception ex)
		{
			AppendToLocalLog("KillQSPR() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("KillQSPR() okay");
		return true;
	}

	public bool CloseQSPR()
	{
		try
		{
			if (!qsprProcess.CloseMainWindow())
			{
				AppendToLocalLog("CloseMainWindow() returned false");
			}
			else
			{
				AppendToLocalLog("CloseMainWindow() returned true");
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("CloseQSPR() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("CloseQSPR() okay");
		return true;
	}

	public bool VerifyProcess()
	{
		try
		{
			if (qsprProcess.HasExited)
			{
				AppendToLocalLog("VerifyProcess() failed: process.HasExited == true");
				return false;
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("VerifyProcess() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("VerifyProcess(): okay");
		return true;
	}

	public bool VerifyConnection()
	{
		try
		{
			string text = instanceIdentifier + " checking in";
			int num = 1;
			while (num <= 10)
			{
				AppendToLocalLog($"VerifyConnection(): Attempt {num} Pinging server with message:{text} ");
				string text2 = qsprAutomation.Ping(instanceIdentifier + " checking in");
				if (text2 != text)
				{
					AppendToLocalLog($"VerifyConnection(): failed. Got message from server on attempt{num}:{text2} ");
				}
				else
				{
					AppendToLocalLog("Verifying Process and Port match");
					bool processMatched = true;
					if (VerifyProcessPort(portNumber, out processMatched))
					{
						AppendToLocalLog("VerifyConnection(): okay");
						return true;
					}
					if (!processMatched)
					{
						portMisMatch = true;
						AppendToLocalLog("VerifyConnection(): failed, server process id doesn't match ");
						return false;
					}
				}
				num++;
				Thread.Sleep(3000);
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("VerifyConnection() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("VerifyConnection(): failed exhausted all attempts ");
		return false;
	}

	public bool RunTree(string uuid, int phoneIndex)
	{
		string additionalInformation = uuid + messageArgSeparator + phoneIndex;
		return SendSpecialMessageToQSPR("Run Tree", additionalInformation);
	}

	public bool RunTreeFromPrevLastSn(int phoneIndex)
	{
		string additionalInformation = "UseLastSN" + messageArgSeparator + phoneIndex;
		return SendSpecialMessageToQSPR("Run Tree", additionalInformation);
	}

	public bool StopTree()
	{
		return SendMenuMessageToQSPR("Stop Tree");
	}

	public bool XTTStop()
	{
		return StopTree();
	}

	public bool XTTAbort()
	{
		return SendMenuMessageToQSPR("Abort");
	}

	public bool OpenXTT(string fileName)
	{
		return SendSpecialMessageToQSPR("Open", fileName);
	}

	public bool OpenTestPlan(long id, int versionNumber, string databaseServer, string databaseName)
	{
		string additionalInformation = string.Format("{0}{4}{1}{4}{2}{4}{3}", id, versionNumber, databaseServer, databaseName, messageArgSeparator);
		return SendSpecialMessageToQSPR("Open Test Plan", additionalInformation);
	}

	internal bool OpenTestPlan(string name, int versionNumber, string databaseServer, string databaseName)
	{
		string additionalInformation = string.Format("{0}{4}{1}{4}{2}{4}{3}", name, versionNumber, databaseServer, databaseName, messageArgSeparator);
		return SendSpecialMessageToQSPR("Open Test Plan", additionalInformation);
	}

	public bool SelectTestsByIndex(string guids)
	{
		return SendSpecialMessageToQSPR("Select Tests By Index", guids);
	}

	public bool SelectTestsByName(string names)
	{
		return SendSpecialMessageToQSPR("Select Tests By Name", names);
	}

	public bool NewXTT()
	{
		return SendSpecialMessageToQSPR("New", "");
	}

	public bool Exit()
	{
		return SendSpecialMessageToQSPR("Exit", "");
	}

	public bool SetRootName(string newRootName)
	{
		return SendSpecialMessageToQSPR("Set Root Name", newRootName);
	}

	public string CreateFolder(string subFolderName, string destinationName, bool isTestIndex)
	{
		string additionalInformation = subFolderName + messageArgSeparator + destinationName + messageArgSeparator + folderInsertPosition.ToString("G") + messageArgSeparator + isTestIndex;
		object obj = SendSpecialMessageToQSPRAndReceiveData("Create Folder", additionalInformation);
		return obj as string;
	}

	public bool SetUserInput(string sCaption, string sLabel, string sUserInput)
	{
		string additionalInformation = sCaption + messageArgSeparator + sLabel + messageArgSeparator + sUserInput;
		return SendSpecialMessageToQSPR("Set User Input", additionalInformation);
	}

	public bool SetUUTId(string serialNumber, int phoneIndex)
	{
		string additionalInformation = serialNumber + messageArgSeparator + phoneIndex;
		return SendSpecialMessageToQSPR("Set Serial Number", additionalInformation);
	}

	public bool SetFolderInsertPosition(int insertPosition)
	{
		bool result = true;
		switch (insertPosition)
		{
		case 0:
			folderInsertPosition = Position.First;
			break;
		case 1:
			folderInsertPosition = Position.Last;
			break;
		default:
			result = false;
			break;
		}
		return result;
	}

	public bool RemoveRootFolder(int removeRoot)
	{
		bool result = true;
		switch (removeRoot)
		{
		case 0:
			removeRootFolder = false;
			break;
		case 1:
			removeRootFolder = true;
			break;
		default:
			result = false;
			break;
		}
		return result;
	}

	public bool RenameTest(string previouseTest, string newTest)
	{
		string additionalInformation = previouseTest + messageArgSeparator + newTest;
		return SendSpecialMessageToQSPR("Rename Test", additionalInformation);
	}

	public bool DeleteTest(string testName)
	{
		return SendSpecialMessageToQSPR("DeleteTest", testName);
	}

	public bool SetNodeDescription(string nodeName, string description)
	{
		string additionalInformation = nodeName + messageArgSeparator + description;
		return SendSpecialMessageToQSPR("Set Node Description", additionalInformation);
	}

	public bool SetNodeNotes(string nodeName, string nodeNotes)
	{
		string additionalInformation = nodeName + messageArgSeparator + nodeNotes;
		return SendSpecialMessageToQSPR("Set Node Notes", additionalInformation);
	}

	public bool SetLoopType(string testName, int countdownValue, string parameterName, string loopValue, int loopType, bool isTestIndex, string testToUpdate, string loopName)
	{
		string text = "";
		text = string.Join(messageArgSeparator, testName, countdownValue.ToString(), parameterName, loopValue, loopType.ToString(), isTestIndex.ToString(), testToUpdate, loopName);
		return SendSpecialMessageToQSPR("Set Loop Type", text);
	}

	public bool SetLoopTypeInFolder(string folderName, int countdownValue, string parameterName, string loopValue, int loopType, string inFolderName)
	{
		string additionalInformation = string.Join(messageArgSeparator, folderName, countdownValue.ToString(), parameterName, loopValue, loopType.ToString(), inFolderName);
		return SendSpecialMessageToQSPR("Set Loop Type In Folder", additionalInformation);
	}

	public bool SetTestParameter(string testName, string paramName, string paramValue, string lowerLimit, string upperLimit, bool isTestIndex)
	{
		string additionalInformation = paramName + messageArgSeparator + paramValue + messageArgSeparator + testName + messageArgSeparator + lowerLimit + messageArgSeparator + upperLimit + messageArgSeparator + isTestIndex;
		return SendSpecialMessageToQSPR("Set Test Parameter", additionalInformation);
	}

	public bool SetTestParameterInAllTests(string paramName, string paramValue)
	{
		string additionalInformation = paramName + messageArgSeparator + paramValue;
		return SendSpecialMessageToQSPR("Set Test Parameter In All Tests", additionalInformation);
	}

	public bool SetTestParametersInFolder(string paramName, string paramValue, string testTreeFolderName)
	{
		string additionalInformation = paramName + messageArgSeparator + paramValue + messageArgSeparator + testTreeFolderName;
		return SendSpecialMessageToQSPR("Set Test Parameter In Folder", additionalInformation);
	}

	public bool SetSkipRunSequence(string testName, SkipRunSequence skipSequenceEnum)
	{
		string text = testName + messageArgSeparator;
		if (skipSequenceEnum == SkipRunSequence.Always)
		{
			text += "Always";
		}
		if (skipSequenceEnum == SkipRunSequence.Never)
		{
			text += "Never";
		}
		if (skipSequenceEnum == SkipRunSequence.Fail)
		{
			text += "Fail";
		}
		if (skipSequenceEnum == SkipRunSequence.Pass)
		{
			text += "Pass";
		}
		if (skipSequenceEnum == SkipRunSequence.Pass)
		{
			text += "Locked";
		}
		if (skipSequenceEnum == SkipRunSequence.Pass)
		{
			text += "LinkedToAnotherDocument";
		}
		return SendSpecialMessageToQSPR("Set Skip Run Sequence", text);
	}

	public bool ImportTests(string testList, string sourceTestTree, string destinationTestOrFolder, bool insertInFolder, Position positionWithInFolder)
	{
		string text = "";
		text = ((!insertInFolder) ? (removeRootFolder + messageArgSeparator + testList + messageArgSeparator + sourceTestTree + messageArgSeparator + destinationTestOrFolder + messageArgSeparator + insertInFolder + messageArgSeparator) : (removeRootFolder + messageArgSeparator + testList + messageArgSeparator + sourceTestTree + messageArgSeparator + destinationTestOrFolder + messageArgSeparator + insertInFolder + messageArgSeparator + positionWithInFolder));
		return SendSpecialMessageToQSPR("Import Tests", text);
	}

	public int GoNoGoStatus()
	{
		int num = 0;
		try
		{
			num = qsprAutomation.GetTestTreeStatus();
			qspr2Compatibility = new QSPR2Compatability();
			num = qspr2Compatibility.GetMappedTestStatus((TestResult)num);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("GetTestTreeStatus() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return -99;
		}
		AppendToLocalLog("GetTestTreeStatus() okay");
		return num;
	}

	public bool Save()
	{
		return SendSpecialMessageToQSPR("Save", "");
	}

	public bool SaveAs(string fileName)
	{
		return SendSpecialMessageToQSPR("SaveAs", fileName);
	}

	public bool SuppressAllMessages(bool supress)
	{
		string additionalInformation = supress.ToString();
		return SendSpecialMessageToQSPR("Suppress All Messages", additionalInformation);
	}

	public bool EnableTracing(bool enable)
	{
		string additionalInformation = enable.ToString();
		return SendSpecialMessageToQSPR("Enable Tracing", additionalInformation);
	}

	public bool SuppressResultsDialog(bool supress)
	{
		string additionalInformation = supress.ToString();
		return SendSpecialMessageToQSPR("Suppress Results Dialog", additionalInformation);
	}

	public bool SuppressSerialNumberDialog(bool supress)
	{
		string additionalInformation = supress.ToString();
		return SendSpecialMessageToQSPR("Suppress SN Dialog", additionalInformation);
	}

	public bool ClearLog()
	{
		try
		{
			qsprAutomation.ClearLog();
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ClearLog() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("ClearLog() okay");
		return true;
	}

	public bool AppendToLog(string message)
	{
		try
		{
			qsprAutomation.AppendToLog(message);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("AppendToLog(" + message + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("AppendToLog(" + message + ") okay");
		return true;
	}

	public bool SendMenuMessageToQSPR(string message)
	{
		try
		{
			qsprAutomation.SendMenuMessageToQSPR(message);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("SendMenuMessageToQSPR(" + message + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("SendMenuMessageToQSPR(" + message + ") okay");
		return true;
	}

	public bool SendSpecialMessageToQSPR(string message, string additionalInformation)
	{
		bool result = false;
		try
		{
			object obj = qsprAutomation.SendSpecialMessageToQSPR(message, additionalInformation);
			if (obj != null && obj is string)
			{
				if (!bool.TryParse(obj as string, out result))
				{
					result = false;
				}
			}
			else
			{
				result = false;
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("SendSpecialMessageToQSPR(" + message + ", " + additionalInformation + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("SendSpecialMessageToQSPR(" + message + ") okay");
		return result;
	}

	public object SendSpecialMessageToQSPRAndReceiveData(string message, string additionalInformation)
	{
		object obj = null;
		try
		{
			obj = qsprAutomation.SendSpecialMessageToQSPR(message, additionalInformation);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("SendSpecialMessageToQSPRAndReceiveCallBack(" + message + ", " + additionalInformation + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return default(CallbackResultInfo);
		}
		AppendToLocalLog("SendSpecialMessageToQSPRAndReceiveCallBack(" + message + ") okay");
		return obj;
	}

	public bool SetGlobalVariable(string variableName, string value)
	{
		try
		{
			if (!qsprAutomation.SetGlobalVariable(variableName, value))
			{
				AppendToLocalLog("SetGlobalVariable(" + variableName + "," + value + ") failed: qsprAutomation.SetGlobalVariable() failed");
				return false;
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("SetGlobalVariable(" + variableName + "," + value + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("SetGlobalVariable(" + variableName + "," + value + ") okay");
		return true;
	}

	public bool GetGlobalVariable(string variableName, out string value)
	{
		value = "";
		try
		{
			value = qsprAutomation.GetGlobalVariable(variableName);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("GetGlobalVariable(" + variableName + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("GetGlobalVariable(" + variableName + ") okay");
		return true;
	}

	public bool SetConfigInfo(bool clearPrevious, string variableName, string value, bool includeInTestResults)
	{
		try
		{
			qsprAutomation.SetConfigInfo(clearPrevious, variableName, value, includeInTestResults);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("SetConfigInfo(" + clearPrevious + ", " + variableName + ", " + value + ", " + includeInTestResults + ") failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("SetConfigInfo(" + clearPrevious + ", " + variableName + "," + value + ") okay");
		return true;
	}

	public bool ShowWindow()
	{
		bool flag = true;
		try
		{
			AppendToLocalLog("ShowWindow(), window handle is " + qsprProcess.MainWindowHandle);
			flag = SendSpecialMessageToQSPR("Show Window", "");
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ShowWindow() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			flag = false;
		}
		if (qsprShownDelegate != null)
		{
			qsprShownDelegate(flag);
		}
		if (flag)
		{
			AppendToLocalLog("ShowWindow(): okay");
		}
		return flag;
	}

	public bool HideWindow()
	{
		bool flag = true;
		try
		{
			AppendToLocalLog("HideWindow(), window handle is " + qsprProcess.MainWindowHandle);
			flag = SendSpecialMessageToQSPR("Hide Window", "");
		}
		catch (Exception ex)
		{
			AppendToLocalLog("HideWindow() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			flag = false;
		}
		if (qsprHiddenDelegate != null)
		{
			qsprHiddenDelegate(flag);
		}
		if (flag)
		{
			AppendToLocalLog("HideWindow(): okay");
		}
		return flag;
	}

	private bool StartProcess()
	{
		try
		{
			qsprProcess = new Process();
			qsprProcess.EnableRaisingEvents = false;
			qsprProcess.StartInfo.FileName = qsprExecutablePath;
			qsprProcess.StartInfo.Arguments = initialTestTreeName + " /gv:AUTOMATION_SERVER_PORT_NUMBER=" + portNumber + " /mode:auto  " + qsprAdditionalCommandLineParameters;
			qsprProcess.EnableRaisingEvents = true;
			qsprProcess.Exited += qsprProcess_Exited;
			AppendToLocalLog("StartProcess(): qsprProcess.StartInfo.FileName = " + qsprProcess.StartInfo.FileName);
			AppendToLocalLog("StartProcess(): qsprProcess.StartInfo.Arguments = " + qsprProcess.StartInfo.Arguments);
			qsprProcess.Start();
			qsprProcess.WaitForInputIdle();
			AppendToLocalLog("StartProcess(): qsprProcess PID = " + qsprProcess.Id);
			if (qsprStartedDelegate != null)
			{
				qsprStartedDelegate();
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("StartProcess() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("StartProcess(): okay");
		return true;
	}

	private bool StartProcessWithDefaultArgs(bool hidden, string backgroundColor)
	{
		try
		{
			qsprProcess = new Process();
			qsprProcess.EnableRaisingEvents = false;
			qsprProcess.StartInfo.FileName = qsprExecutablePath;
			string text = string.Empty;
			if (!string.IsNullOrEmpty(backgroundColor))
			{
				text = " /bgcolor:" + backgroundColor;
			}
			string text2 = string.Empty;
			if (hidden)
			{
				text2 = " /hide ";
			}
			qsprProcess.StartInfo.Arguments = text2 + " /gv:AUTOMATION_SERVER_PORT_NUMBER=" + portNumber + " /mode:auto  /suppressMessages /nosplashscreen" + text;
			AppendToLocalLog("Command line arguments = " + qsprProcess.StartInfo.Arguments);
			qsprProcess.EnableRaisingEvents = true;
			qsprProcess.Exited += qsprProcess_Exited;
			AppendToLocalLog("StartProcessWithoutArgs(): qsprProcess.StartInfo.FileName = " + qsprProcess.StartInfo.FileName);
			AppendToLocalLog("StartProcessWithoutArgs(): qsprProcess.StartInfo.Arguments = " + qsprProcess.StartInfo.Arguments);
			qsprProcess.Start();
			qsprProcess.WaitForInputIdle();
			AppendToLocalLog("QSPR process started with qsprProcess.Id = " + qsprProcess.Id);
			if (qsprStartedDelegate != null)
			{
				qsprStartedDelegate();
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("StartProcessWithoutArgs() failed: caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("StartProcessWithoutArgs(): okay");
		return true;
	}

	private void qsprProcess_Exited(object sender, EventArgs e)
	{
		AppendToLocalLog("QSPR exited with error code " + qsprProcess.ExitCode);
		if (qsprExitedDelegate != null)
		{
			qsprExitedDelegate(instanceIdentifier, qsprProcess.ExitCode);
		}
	}

	private bool ConnectToServer()
	{
		try
		{
			AppendToLocalLog("Connecting to server on port number " + portNumber);
			qsprAutomation = (RemoteableObject)Activator.GetObject(typeof(RemoteableObject), "tcp://127.0.0.1:" + portNumber + "/QSPRAutomationPlugin");
			if (qsprAutomation == null)
			{
				AppendToLocalLog("ConnectToServer() failed: qsprAutomation == null");
				return false;
			}
			if (!VerifyConnection())
			{
				AppendToLocalLog("ConnectToServer() failed: VerifyConnection() failed");
				return false;
			}
			qsprAutomation.sendMessageFromQSPRDelegate = SendMessageFromQSPRShim.Wrap(ProcessMessageFromQSPR);
			qsprAutomation.sendDebugMessageFromQSPRDelegate = SendDebugMessageFromQSPRShim.Wrap(ProcessDebugMessageFromQSPR);
			qsprAutomation.globalVariableModifiedDelegate = GlobalVaiablesModifiedShim.Wrap(ProcessGlobalVariableModified);
			qsprAutomation.TestMessageReceived = TestMessageShim.Wrap(HandleAutomationTestMessage);
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ConnectToServer(): caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("ConnectToServer(): okay");
		return true;
	}

	private void HandleAutomationTestMessage(object message)
	{
		if (TestMessageReceived != null)
		{
			TestMessageReceived(message);
		}
	}

	private bool ConnectToServer(int tries, int delayBetweenTriesMs)
	{
		try
		{
			for (int i = 0; i < tries; i++)
			{
				Thread.Sleep(delayBetweenTriesMs);
				if (ConnectToServer())
				{
					AppendToLocalLog("ConnectToServer(" + tries + ", " + delayBetweenTriesMs + "): okay");
					return true;
				}
				if (portMisMatch)
				{
					portMisMatch = false;
					return false;
				}
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ConnectToServer(" + tries + ", " + delayBetweenTriesMs + "): caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
			return false;
		}
		AppendToLocalLog("ConnectToServer(" + tries + ", " + delayBetweenTriesMs + "): giving up");
		return false;
	}

	public void AppendToLocalLog(string message)
	{
		if (appendToLocalLogDelegate != null)
		{
			appendToLocalLogDelegate(instanceIdentifier, message);
		}
	}

	private void ProcessGlobalVariableModified(string gvName, string gvValue)
	{
		try
		{
			if (processGlobalVariablesModifiedDelegate != null)
			{
				processGlobalVariablesModifiedDelegate(instanceIdentifier, gvName, gvValue);
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ProcessGlobalVariableModified(): caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
		}
	}

	public void SendQSPRDebugMessages()
	{
		SendSpecialMessageToQSPR(SEND_QSPR_DEBUG_MESSAGES, bool.TrueString);
	}

	public void StopSendingQSPRDebugMessages()
	{
		SendSpecialMessageToQSPR(SEND_QSPR_DEBUG_MESSAGES, bool.FalseString);
	}

	private void ProcessDebugMessageFromQSPR(string windowName, string text, int traceLevel)
	{
		try
		{
			if (processReceivedQSPRDebugMessageDelegate != null)
			{
				processReceivedQSPRDebugMessageDelegate(instanceIdentifier, windowName, text, traceLevel);
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ProcessDebugMessageFromQSPR(): caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
		}
	}

	private void ProcessMessageFromQSPR(string serializedMessage)
	{
		try
		{
			if (processReceivedQSPRMessageDelegate != null)
			{
				XmlSerializer xmlSerializer = new XmlSerializer(typeof(MsgData));
				MsgData msgData = (MsgData)xmlSerializer.Deserialize(new StringReader(serializedMessage));
				processReceivedQSPRMessageDelegate(instanceIdentifier, msgData);
			}
		}
		catch (Exception ex)
		{
			AppendToLocalLog("ProcessMessageFromQSPR(): caught exception:\r\nSource: " + ex.Source + "\r\nMessage: " + ex.Message);
		}
	}

	public string GetNodeNotes(string nodeName)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Node Notes", nodeName);
		if (obj is string result)
		{
			return result;
		}
		return null;
	}

	public string GetNodeDescription(string nodeName)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Node Description", nodeName);
		if (obj is string result)
		{
			return result;
		}
		return null;
	}

	public bool SyncTest(string testName)
	{
		return SendSpecialMessageToQSPR("Synchronize", testName);
	}

	public bool AddDllPath(string dllPath)
	{
		return SendSpecialMessageToQSPR("Add DLL Path", dllPath);
	}

	public bool EnableDllSearchPaths(int enable)
	{
		return SendSpecialMessageToQSPR("Enable DLL Paths", enable.ToString());
	}

	public bool AddTestContainer(string containerPath, QTMTestTypes testType)
	{
		string text = containerPath;
		switch (testType)
		{
		case QTMTestTypes.CTSTest:
			text = text + messageArgSeparator + "CTSTest";
			break;
		case QTMTestTypes.HiveTest:
			text = text + messageArgSeparator + "HiveTest";
			break;
		case QTMTestTypes.ScriptTest:
			text = text + messageArgSeparator + "ScriptTest";
			break;
		case QTMTestTypes.LabVIEWTest:
			text = text + messageArgSeparator + "LabVIEWTest";
			break;
		case QTMTestTypes.DotNetTest:
			text = text + messageArgSeparator + "DotNetTest";
			break;
		}
		if (testType == QTMTestTypes.ScriptTest)
		{
			return SendSpecialMessageToQSPR("Add Script", text);
		}
		return SendSpecialMessageToQSPR("Add DLL", text);
	}

	public string GetTestIndex(string testName)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Test Index", testName);
		return obj as string;
	}

	public string AddTest(string realName, string newTestName, string destinationIndex, int position)
	{
		string additionalInformation = realName + messageArgSeparator + newTestName + messageArgSeparator + destinationIndex + messageArgSeparator + position;
		object obj = SendSpecialMessageToQSPRAndReceiveData("AddTest", additionalInformation);
		return obj as string;
	}

	public bool CreateConditionOnTestParam(string conditionName, int conditionType, string testName, string testIndex, string paramName, int statementType, int valueType, object value)
	{
		string additionalInformation = string.Join(messageArgSeparator, conditionName, conditionType.ToString(), testName, testIndex, paramName, statementType.ToString(), valueType.ToString(), value.ToString());
		return SendSpecialMessageToQSPR("Create Condition On Test Parameter", additionalInformation);
	}

	public bool CreateConditionOnTestResult(string conditionName, int conditionType, string testName, string testIndex, int testResult)
	{
		string additionalInformation = string.Join(messageArgSeparator, conditionName, conditionType.ToString(), testName, testIndex, testResult.ToString());
		return SendSpecialMessageToQSPR("Create Condition On Test Result", additionalInformation);
	}

	public bool CreateConditionOnGlobal(string conditionName, int conditionType, string testIndex, string globalName, int statementType, int valueType, object value)
	{
		string additionalInformation = string.Join(messageArgSeparator, conditionName, conditionType.ToString(), testIndex, globalName, statementType.ToString(), valueType.ToString(), value.ToString());
		return SendSpecialMessageToQSPR("Create Condition On Global Variable", additionalInformation);
	}

	public bool SetCondition(string testIndex, int conditionType, string formula, int runCondition, int action, string branchToTestName)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, conditionType.ToString(), formula, runCondition.ToString(), action.ToString(), branchToTestName);
		return SendSpecialMessageToQSPR("Set Test Condition", additionalInformation);
	}

	public bool SetConditionActive(string testIndex, int conditionType, int conditionActive)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, conditionType.ToString(), conditionActive.ToString());
		return SendSpecialMessageToQSPR("Set Test Condition Active", additionalInformation);
	}

	public bool SetTestProperty(string testIndex, string propertyName, object value)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, propertyName, value.ToString());
		return SendSpecialMessageToQSPR("Set Test Property", additionalInformation);
	}

	public bool ExportToTextFile(string testIndex, string filePath, int includeProperties, int includeParameters, int includeGlobalVals, int includeNotes, int includeLoop)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, filePath, includeProperties.ToString(), includeParameters.ToString(), includeGlobalVals.ToString(), includeNotes.ToString(), includeLoop.ToString());
		return SendSpecialMessageToQSPR("Export Node to Text File", additionalInformation);
	}

	public bool AddScriptParameter(string scriptTestName, string parameterName, int ioType, int dataType, string value, string unit, string description, string lowerLimit, string upperLimit)
	{
		string additionalInformation = string.Join(messageArgSeparator, scriptTestName, parameterName, ioType.ToString(), dataType.ToString(), value, unit, description, lowerLimit, upperLimit);
		return SendSpecialMessageToQSPR("Add Script Parameter", additionalInformation);
	}

	public bool EnableRegexSupport(int enable)
	{
		return SendSpecialMessageToQSPR("Enable Regular Expression Support", enable.ToString());
	}

	internal bool RegisterTree(string serverName, string databaseName, int registerWithoutDB)
	{
		string additionalInformation = string.Join(messageArgSeparator, serverName, databaseName, registerWithoutDB.ToString());
		return SendSpecialMessageToQSPR("RegisterTree", additionalInformation);
	}

	internal bool SetParameterLimits(string TestName, string ParamName, string LowerLimit, string UpperLimit)
	{
		string additionalInformation = string.Join(messageArgSeparator, TestName, ParamName, LowerLimit, UpperLimit);
		return SendSpecialMessageToQSPR("Set Parameter Limits", additionalInformation);
	}

	internal string GetVersion()
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Version", "");
		if (obj is string result)
		{
			return result;
		}
		return "";
	}

	internal bool SaveAsQSPRFormat(string treeFilePath)
	{
		return SendSpecialMessageToQSPR("Save As QSPR Format", treeFilePath);
	}

	internal object GetTestParameterValue(string paramName, string testIndex, int convertToString)
	{
		string additionalInformation = paramName + messageArgSeparator + testIndex + messageArgSeparator + convertToString;
		return SendSpecialMessageToQSPRAndReceiveData("Get Test Parameter Value", additionalInformation);
	}

	internal object GetTestPropertyValue(string propertyName, string testIndex, int convertToString)
	{
		string additionalInformation = propertyName + messageArgSeparator + testIndex + messageArgSeparator + convertToString;
		return SendSpecialMessageToQSPRAndReceiveData("Get Test Property Value", additionalInformation);
	}

	internal string GetNode(string testIndex, NextNodePosition position)
	{
		string additionalInformation = testIndex + messageArgSeparator + (int)position;
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Next Node", additionalInformation);
		return obj as string;
	}

	internal string GetTestParamLimit(string testIndex, string paramName, int limitType)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, paramName, limitType.ToString());
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Parameter Limit", additionalInformation);
		return obj as string;
	}

	internal string GetTestParamUnits(string testIndex, string paramName)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, paramName);
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Parameter Units", additionalInformation);
		return obj as string;
	}

	internal int IsFolder(string testIndex)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Is Node Folder", testIndex);
		int result = -1;
		int.TryParse(obj.ToString(), out result);
		return result;
	}

	internal bool SetTestParamUnits(string testIndex, string paramName, string units)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, paramName, units);
		return SendSpecialMessageToQSPR("Set Parameter Units", additionalInformation);
	}

	internal bool SetTestParamLimit(string testIndex, string paramName, string limitValue, int limitType)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, paramName, limitValue, limitType.ToString());
		return SendSpecialMessageToQSPR("Set Parameter Limit", additionalInformation);
	}

	internal bool ErrorsExist()
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Errors Exist", "");
		return bool.Parse(obj as string);
	}

	internal bool SetErrorsExist(int value)
	{
		return SendSpecialMessageToQSPR("Set Errors Exist", value.ToString());
	}

	internal int GetTestChecked(string testIndex)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Test Checked", testIndex);
		return int.Parse(obj.ToString());
	}

	internal bool SetTestChecked(string testIndex, int value)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, value.ToString());
		return SendSpecialMessageToQSPR("Set Test Checked", additionalInformation);
	}

	internal string GetParentNode(string testIndex)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Parent Node", testIndex);
		return obj as string;
	}

	internal bool EnableLoopRow(string testName, int rowID, bool enableRow, bool isTestIndex)
	{
		string additionalInformation = string.Join(messageArgSeparator, testName, rowID.ToString(), enableRow.ToString(), isTestIndex.ToString());
		return SendSpecialMessageToQSPR("Enable Loop Row", additionalInformation);
	}

	internal string GetLoopNames(string testIndex)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Loop Names", testIndex);
		return obj as string;
	}

	internal string GetLoopRowsEnabled(string testIndex)
	{
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Loop Rows Enabled", testIndex);
		return obj as string;
	}

	internal string GetParamLoopedTestName(string testIndex, string loopName)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, loopName);
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Param Looped Test Name", additionalInformation);
		return obj as string;
	}

	internal string GetLoopParamName(string testIndex, string loopName)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, loopName);
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Loop Param Name", additionalInformation);
		return obj as string;
	}

	internal bool RunTest(string testName)
	{
		return SendSpecialMessageToQSPR("Run Test", testName);
	}

	internal string CopyTest(string DestinationFolder, string newTestName, string currTestIndex, int position)
	{
		string additionalInformation = DestinationFolder + messageArgSeparator + newTestName + messageArgSeparator + currTestIndex + messageArgSeparator + position;
		object obj = SendSpecialMessageToQSPRAndReceiveData("Copy", additionalInformation);
		string text = obj as string;
		if (!Guid.TryParse(text, out var _))
		{
			text = null;
		}
		return text;
	}

	internal bool SetTestParamGv(string message, string testIndex, string ParamName, string GvName)
	{
		string additionalInformation = string.Join(messageArgSeparator, testIndex, ParamName, GvName);
		return SendSpecialMessageToQSPR(message, additionalInformation);
	}

	internal bool EnableLoopValues(string TestName, string LoopName, string Values, bool Enable, bool isTestIndex = false)
	{
		if (Values.Contains(messageArgSeparator))
		{
			Values = Values.Replace(messageArgSeparator, "#@#");
		}
		string additionalInformation = string.Join(messageArgSeparator, TestName, LoopName, Values, Enable.ToString(), isTestIndex.ToString());
		return SendSpecialMessageToQSPR("Enable Loop Values", additionalInformation);
	}

	internal bool EnableDataLogging(string TestName, string ParamName, bool Enable, bool isTestIndex = false)
	{
		string additionalInformation = string.Join(messageArgSeparator, TestName, ParamName, Enable.ToString(), isTestIndex.ToString());
		return SendSpecialMessageToQSPR("Enable DataLogging", additionalInformation);
	}

	internal string GetLoopValues(string TestName, string LoopName, bool isTestIndex = false)
	{
		string additionalInformation = TestName + messageArgSeparator + LoopName + messageArgSeparator + isTestIndex;
		object obj = SendSpecialMessageToQSPRAndReceiveData("Get Loop Values", additionalInformation);
		return obj as string;
	}

	internal bool SetSecurityLevel(int securityLevel)
	{
		return SendSpecialMessageToQSPR("Set Security Level", securityLevel.ToString());
	}

	internal bool ResumeTree()
	{
		return SendSpecialMessageToQSPR("Resume Tree", "");
	}
}
