using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Forms;
using System.Xml.Serialization;
using QC.QsprShared.Dialogs;
using QC.QsprShared.Trace;
using QC.QsprTestObjects.Parameters;
using QC.QsprTestObjects.Tests.Base;
using QC.QTMInterface;

namespace QC.QsprTestObjects.Registry;

public class QTMRegistry : INotifyPropertyChanged
{
	private const string THISPC = "This PC";

	private Hashtable hashTargets = new Hashtable();

	private ObservableCollection<QTMTarget> arrayTargets = new ObservableCollection<QTMTarget>();

	[NonSerialized]
	[XmlIgnore]
	public Scheduler scheduler;

	private bool isSelected;

	private bool expanded;

	private string key;

	[XmlIgnore]
	public bool IsSelected
	{
		get
		{
			return isSelected;
		}
		set
		{
			isSelected = value;
			RaiseOnPropertyChanged("IsSelected");
		}
	}

	[XmlIgnore]
	public bool Expanded
	{
		get
		{
			return expanded;
		}
		set
		{
			expanded = value;
			RaiseOnPropertyChanged("Expanded");
		}
	}

	[XmlIgnore]
	public string Key
	{
		get
		{
			return key;
		}
		set
		{
			key = value;
		}
	}

	[XmlIgnore]
	public Hashtable Targets
	{
		get
		{
			return hashTargets;
		}
		set
		{
			hashTargets = value;
		}
	}

	[XmlElement(Type = typeof(QTMTarget))]
	[XmlElement(Type = typeof(QTMThisPCTarget))]
	public ObservableCollection<QTMTarget> Target
	{
		get
		{
			return arrayTargets;
		}
		set
		{
			arrayTargets = value;
		}
	}

	[XmlIgnore]
	public MessageDelegate QTMMessageDelegate => scheduler.msgDelegate;

	[field: XmlIgnore]
	public event PropertyChangedEventHandler PropertyChanged;

	public QTMTarget Add(string targetName, QTMTargetType tType)
	{
		if (hashTargets.Contains(targetName))
		{
			return (QTMTarget)hashTargets[targetName];
		}
		if (tType == QTMTargetType.ThisPC)
		{
			QTMThisPCTarget qTMThisPCTarget = new QTMThisPCTarget(targetName);
			qTMThisPCTarget.theRegistry = this;
			hashTargets.Add(targetName, qTMThisPCTarget);
			arrayTargets.Add(qTMThisPCTarget);
			return qTMThisPCTarget;
		}
		return null;
	}

	public void CreateHastable()
	{
		hashTargets = new Hashtable();
		foreach (QTMTarget arrayTarget in arrayTargets)
		{
			arrayTarget.theRegistry = this;
			arrayTarget.theRegistry.scheduler = scheduler;
			arrayTarget.CreateHashtable();
			hashTargets.Add(arrayTarget.Name, arrayTarget);
		}
		if (arrayTargets.Count == 0)
		{
			Add("This PC", QTMTargetType.ThisPC);
		}
	}

	public bool AppendTarget(QTMTarget importedTarget)
	{
		bool result = false;
		try
		{
			if (!hashTargets.ContainsKey(importedTarget.Name))
			{
				Add(importedTarget.Name, importedTarget.TargetType);
			}
			foreach (QTMTestContainer value in importedTarget.HashContainers.Values)
			{
				string[] array = value.Name.Trim().Split('\\');
				if (!ContainerExists((QTMTarget)hashTargets[value.TargetName], array[array.Length - 1].ToString()))
				{
					((QTMTarget)hashTargets[importedTarget.Name]).AddContainer(value);
				}
			}
			return result;
		}
		catch (Exception ex)
		{
			throw new Exception("AppendTarget failed, " + ex.Message);
		}
	}

	public void SetGlobalVariable(string Name, string Value)
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				value.SetGlobalVariable(Name, Value);
			}
		}
		catch
		{
		}
	}

	public void SetGlobalVariable(string Name, object Value)
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				value.SetGlobalVariable(Name, Value);
			}
		}
		catch
		{
		}
	}

	public void SetGlobalVariable(string Name, int Value)
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				value.SetGlobalVariable(Name, Value);
			}
		}
		catch
		{
		}
	}

	public void UpdateToolTipVisibility(Visibility visibility)
	{
		foreach (QTMTestContainer testContainer in Target[0].TestContainers)
		{
			testContainer.UserInterfaceProperties.ToolTipVisibility = visibility;
			foreach (QTMTestContainerItem item in testContainer.UserInterfaceProperties.Items)
			{
				item.ToolTipVisibility = visibility;
				if (item.Items.Count > 0)
				{
					item.UpdateToolTipVisibility(visibility);
				}
			}
		}
	}

	public QTMTarget GetTarget(string targetName)
	{
		if (hashTargets.Contains(targetName))
		{
			return (QTMTarget)hashTargets[targetName];
		}
		return null;
	}

	public void OnTestMessage(TestMsgType msgType, string testFullPath, TestResult result)
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				value.OnTestMessage(msgType, testFullPath, result);
			}
		}
		catch
		{
		}
	}

	public void MenuMessages(string key)
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				value.MenuMessages(key);
			}
		}
		catch
		{
		}
	}

	private bool ContainerExists(QTMTarget target, string containerName)
	{
		foreach (QTMTestContainer value in target.HashContainers.Values)
		{
			string[] array = value.Name.Trim().Split('\\');
			if (array[array.Length - 1] == containerName)
			{
				return true;
			}
		}
		return false;
	}

	private void ClearTestContainers()
	{
		try
		{
			foreach (QTMTarget value in hashTargets.Values)
			{
				foreach (QTMTestContainer value2 in value.HashContainers.Values)
				{
					try
					{
						if (value2.Loaded)
						{
							value.UnloadContainer(value2.ContainerType, value2.Name);
						}
					}
					catch
					{
					}
				}
				value.CloseKernels();
				value.HashContainers = new Hashtable();
				value.TestContainers = new ObservableCollection<QTMTestContainer>();
			}
		}
		catch
		{
		}
	}

	public void ClearTargets()
	{
		ClearTestContainers();
		QTMThisPCTarget qTMThisPCTarget = (QTMThisPCTarget)hashTargets["This PC"];
		hashTargets = new Hashtable();
		hashTargets.Add("This PC", qTMThisPCTarget);
		arrayTargets = new ObservableCollection<QTMTarget>();
		arrayTargets.Add(qTMThisPCTarget);
	}

	public bool LoadContainer(string testName, string targetName, bool newContainer)
	{
		if (GetContainerForTest(testName, targetName, out var tContainer))
		{
			if (tContainer.Loaded)
			{
				return true;
			}
			return LoadContainer(tContainer, newContainer);
		}
		QTMTarget qTMTarget = (QTMTarget)Targets[targetName];
		foreach (QTMTestContainer value in qTMTarget.HashContainers.Values)
		{
			LoadContainer(value, newContainer);
			foreach (QTMTest value2 in value.HashTests.Values)
			{
				if (value2.Name.Trim() == testName.Trim())
				{
					return true;
				}
			}
		}
		TraceMessage.Write(ToString(), testName + " not found. Load failed.", TraceMessageType.Exception);
		return false;
	}

	public bool LoadContainer(QTMTestContainer testContainer, bool newContainer)
	{
		try
		{
			string listOfTests = testContainer.TestListAsString;
			QTMTarget target = GetTarget(testContainer.TargetName);
			DllLoadedDetails msgDetails = default(DllLoadedDetails);
			if (newContainer || UpdateDllPath(testContainer, out msgDetails))
			{
				if (target.LoadContainer(testContainer, ref listOfTests))
				{
					testContainer.Loaded = true;
					listOfTests = testContainer.TargetName + "," + testContainer.Name + "," + listOfTests;
					testContainer.CreateTestList(listOfTests);
					TestMessage message = default(TestMessage);
					message.Message = listOfTests;
					message.Object = msgDetails;
					try
					{
						message.TestIndex = (testContainer.HideTests ? "true" : "false");
						testContainer.UserInterfaceProperties.DisplayedItems = null;
						testContainer.UserInterfaceProperties.UnloadSupported = testContainer.ContainerType != QC.QsprTestObjects.Tests.Base.QTMTestTypes.DotNetTest;
					}
					catch
					{
					}
					QTMMessageDelegate(TestMsgType.OnDLLLoaded, message);
					return true;
				}
			}
			else
			{
				string text = "DLL Path not found!\n\n" + testContainer.Name;
				if (!scheduler.QTMData.WConfig.UseDllSearch)
				{
					text += "\n\nNote: Enable Dll Path(s) in Workspace Configuration to search\nfor different path(s).";
				}
				AppMessageDialog.Show(text, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Error);
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "LoadContainer failed, " + testContainer.Name + " " + ex.Message, TraceMessageType.Exception);
		}
		return false;
	}

	public bool UpdateDllPath(QTMTestContainer testContainer, out DllLoadedDetails msgDetails)
	{
		FileInfo fileInfo = new FileInfo(testContainer.OriginalName);
		string name = fileInfo.Name;
		msgDetails = default(DllLoadedDetails);
		if (scheduler.QTMData.WConfig.UseDllSearch)
		{
			List<string> list = new List<string>(scheduler.QTMData.WConfig.DLLPaths);
			foreach (string item in list)
			{
				if (File.Exists(Path.Combine(item, name)))
				{
					if (string.Compare(testContainer.OriginalName, Path.Combine(item, name), ignoreCase: true) == 0)
					{
						return true;
					}
					msgDetails = ProcessDllPathChanges(testContainer, fileInfo, name, item);
					return true;
				}
			}
		}
		if (File.Exists(fileInfo.FullName))
		{
			return true;
		}
		string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		if (File.Exists(Path.Combine(directoryName, name)) && string.Compare(testContainer.OriginalName, Path.Combine(directoryName, name), ignoreCase: true) != 0)
		{
			msgDetails = ProcessDllPathChanges(testContainer, fileInfo, name, directoryName);
			return true;
		}
		return false;
	}

	private DllLoadedDetails ProcessDllPathChanges(QTMTestContainer testContainer, FileInfo fInfo, string dllName, string path)
	{
		DllLoadedDetails result = default(DllLoadedDetails);
		testContainer.IsDllPathUpdated = true;
		testContainer.UpdatedDllPathName = Path.Combine(path, dllName);
		QTMTarget target = GetTarget(testContainer.TargetName);
		target.UpdateContainerWithNewPath(testContainer.OriginalName, testContainer.UpdatedDllPathName, testContainer);
		result.DllPathUpdated = true;
		result.newPath = Path.Combine(path, dllName);
		result.oldPath = fInfo.FullName;
		return result;
	}

	public bool GetContainerForTest(string testName, string targetName, out QTMTestContainer tContainer)
	{
		tContainer = null;
		bool flag = false;
		try
		{
			QTMTarget qTMTarget = (QTMTarget)Targets[targetName];
			foreach (QTMTestContainer value in qTMTarget.HashContainers.Values)
			{
				foreach (QTMTest value2 in value.HashTests.Values)
				{
					if (value2.Name.Trim() == testName.Trim())
					{
						tContainer = value;
						flag = true;
						break;
					}
				}
				if (flag)
				{
					break;
				}
			}
			if (flag)
			{
				return true;
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "GetContainerForTest for " + testName + " failed, " + ex.Message, TraceMessageType.Exception);
		}
		return false;
	}

	public ParameterCollection GetParameters(BaseTest sender)
	{
		try
		{
			QTMTarget target = GetTarget(sender.Properties.TargetName);
			QTMTestContainer tContainer = new QTMTestContainer();
			((QTMRegistry)scheduler.QTMData.theRegistry).GetContainerForTest(sender.Properties.RealName, target.Name, out tContainer);
			QTMTest test = tContainer.GetTest(sender.Properties.RealName);
			if (test.ContainerLoadedFirstTime)
			{
				object obj = null;
				if (test.Parameters != null)
				{
					obj = test.Parameters.GetParameterObjectInputFormat();
				}
				target.GetAllParamInfo(sender, sender.Properties.RealName, tContainer.Name, ref obj);
				ParameterCollection parameterCollection2 = (test.Parameters = new ParameterCollection(obj));
				test.ContainerLoadedFirstTime = false;
				return parameterCollection2.SelectedParameters();
			}
			return test.Parameters.SelectedParameters();
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), ex.Message + " GetParameters failed, " + ex.Source, TraceMessageType.Exception);
		}
		return new ParameterCollection();
	}

	public TestProperties GetTestProperties(BaseTest sender)
	{
		try
		{
			QTMTarget target = GetTarget(sender.Properties.TargetName);
			QTMTestContainer tContainer = new QTMTestContainer();
			((QTMRegistry)scheduler.QTMData.theRegistry).GetContainerForTest(sender.Properties.RealName, target.Name, out tContainer);
			QTMTest test = tContainer.GetTest(sender.Properties.RealName);
			return tContainer.GetTestProperties(test.Name);
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "GetTestProperties failed," + ex.Message, TraceMessageType.Exception);
		}
		return sender.Properties;
	}

	public void RunTest(BaseTest sender, ref object objParams, ref object objProperties)
	{
		try
		{
			QTMTarget target = GetTarget(sender.Properties.TargetName);
			GetContainerForTest(sender.Properties.RealName, target.Name, out var tContainer);
			target.SetGlobalVariable("QSPR_ABORT", false.ToString());
			target.SetGlobalVariable("QSPR_STOP", false.ToString());
			target.SetGlobalVariable("QTM_STOP", false.ToString());
			target.SetGlobalVariable("QTM_ABORT", false.ToString());
			target.RunTest(sender, tContainer.Name, ref objParams, ref objProperties);
		}
		catch (Exception ex)
		{
			throw new Exception(ex.Message);
		}
	}

	public string GetTestModulePath(BaseTest sender)
	{
		string result = "";
		try
		{
			QTMTarget target = GetTarget(sender.Properties.TargetName);
			QTMTestContainer tContainer = new QTMTestContainer();
			GetContainerForTest(sender.Properties.RealName, target.Name, out tContainer);
			if (tContainer != null)
			{
				result = (tContainer.IsDllPathUpdated ? tContainer.UpdatedDllPathName : tContainer.Name);
			}
		}
		catch
		{
		}
		return result;
	}

	public Version GetDLLVersion(string dll)
	{
		Version result = null;
		try
		{
			foreach (QTMThisPCTarget value in Targets.Values)
			{
				foreach (QTMTestContainer testContainer in value.TestContainers)
				{
					((QTMRegistry)scheduler.QTMData.theRegistry).UpdateDllPath(testContainer, out var _);
				}
				foreach (QTMTestContainer testContainer2 in value.TestContainers)
				{
					string fileName = Path.GetFileName(testContainer2.Name);
					if (string.Compare(dll, fileName, ignoreCase: true) != 0 || !File.Exists(testContainer2.Name))
					{
						continue;
					}
					FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(testContainer2.Name);
					if (versionInfo.FileVersion != null)
					{
						if (!Version.TryParse(versionInfo.FileVersion, out result))
						{
							result = new Version();
						}
					}
					else
					{
						result = new Version();
					}
					return result;
				}
			}
		}
		catch
		{
		}
		return result;
	}

	public void UpdateDLLVersions()
	{
		foreach (QTMTarget value in Targets.Values)
		{
			foreach (QTMTestContainer testContainer in value.TestContainers)
			{
				testContainer.UpdateDllVersion();
			}
		}
	}

	protected void RaiseOnPropertyChanged(string propertyName)
	{
		if (this.PropertyChanged != null)
		{
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
