using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace QCRPG.Framework;

public sealed class TSLHandler
{
	private const string builderBaseClassFullName = "QCRPG.Framework.BuilderBase";

	private List<Assembly> validLibrariesLoaded = new List<Assembly>();

	private List<BuilderBase> builders = new List<BuilderBase>();

	private List<string> technologyNames = new List<string>();

	private List<Logger> loggers = new List<Logger>();

	private List<Configurer> configurers = new List<Configurer>();

	private List<PacketListBase> packetLists = new List<PacketListBase>();

	private List<APIBase> apis = new List<APIBase>();

	private List<GooierBase> gooiers = new List<GooierBase>();

	private List<ScripterBase> scripters = new List<ScripterBase>();

	private List<List<WorkerThreadBase>> workerThreadLists = new List<List<WorkerThreadBase>>();

	private Dictionary<Configurer, string> configurerToFilenameMap = new Dictionary<Configurer, string>();

	private int DUTNumber = 1;

	private static bool isDutSpecificStackAvailable;

	public TSLHandler(int DUTNumber, bool enableDutSpecificStack = false)
	{
		this.DUTNumber = DUTNumber;
		isDutSpecificStackAvailable = enableDutSpecificStack;
	}

	public void LoadAllLibrariesAndCreateTypes(bool deviceEmulationMode, bool commandLineMode = false)
	{
		validLibrariesLoaded = new List<Assembly>();
		string[] files = Directory.GetFiles(".", "QCRPG.TSL.*.dll");
		string[] files2 = Directory.GetFiles(".", "QCRPG.TSL.*.External.dll");
		List<string> list = new List<string>();
		string[] array = files;
		foreach (string text in array)
		{
			list.Add(text.ToUpper());
		}
		List<string> list2 = new List<string>();
		string[] array2 = files2;
		foreach (string text2 in array2)
		{
			list2.Add(text2.ToUpper());
		}
		List<string> list3 = new List<string>();
		foreach (string item in list)
		{
			if ((!item.EndsWith(".EXTERNAL.DLL") || !list2.Contains(item)) && !LoadAndCheckLibrary(item))
			{
				list3.Add(item);
			}
		}
		foreach (string item2 in list2)
		{
			if (!list.Contains(item2.Replace(".EXTERNAL.DLL", ".DLL")) && !LoadAndCheckLibrary(item2))
			{
				list3.Add(item2);
			}
		}
		CreateBuilders(deviceEmulationMode, commandLineMode, DUTNumber);
		if (list3.Count <= 0)
		{
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		foreach (string item3 in list3)
		{
			stringBuilder.AppendLine("Error loading library " + item3.Trim());
		}
		throw new Exception(stringBuilder.ToString());
	}

	public void LoadOneLibrary(string filename)
	{
		if (!LoadAndCheckLibrary(filename))
		{
			throw new Exception("Error loading library " + filename);
		}
	}

	public List<Assembly> GetValidLibrariesLoaded()
	{
		return validLibrariesLoaded;
	}

	public List<BuilderBase> GetBuilders()
	{
		return builders;
	}

	public List<string> GetTechnologyNames()
	{
		return technologyNames;
	}

	public List<Logger> GetLoggers()
	{
		return loggers;
	}

	public List<Configurer> GetConfigurers()
	{
		return configurers;
	}

	public List<PacketListBase> GetPacketLists()
	{
		return packetLists;
	}

	public List<APIBase> GetAPIs()
	{
		return apis;
	}

	public List<GooierBase> GetGooiers()
	{
		return gooiers;
	}

	public List<ScripterBase> GetScripters()
	{
		return scripters;
	}

	public void StartupLoggers()
	{
		foreach (Logger logger in loggers)
		{
			logger.Startup();
		}
	}

	public void ShutdownLoggers()
	{
		foreach (Logger logger in loggers)
		{
			logger.Shutdown();
		}
	}

	public void LoadConfigurations(XmlSerializer xmlSerializer = null)
	{
		foreach (Configurer configurer in configurers)
		{
			try
			{
				configurer.LoadAndSetConfigurations(configurerToFilenameMap[configurer], xmlSerializer);
			}
			catch (Exception)
			{
			}
		}
	}

	public void SaveConfigurations(XmlSerializer xmlSerializer = null)
	{
		foreach (Configurer configurer in configurers)
		{
			try
			{
				configurer.GetAndSaveConfigurations(configurerToFilenameMap[configurer], xmlSerializer);
			}
			catch (Exception)
			{
			}
		}
	}

	public void StartupAPIs()
	{
		foreach (APIBase api in apis)
		{
			api.Startup();
		}
	}

	public void ShutdownAPIs()
	{
		foreach (APIBase api in apis)
		{
			api.Shutdown();
		}
	}

	public void StartupGooiers()
	{
		foreach (GooierBase gooier in gooiers)
		{
			gooier.Startup();
		}
	}

	public void SetGooiersInvokeControl(Control control)
	{
		foreach (GooierBase gooier in gooiers)
		{
			gooier.InvokeControl = control;
		}
	}

	public void ShutdownGooiers()
	{
		foreach (GooierBase gooier in gooiers)
		{
			gooier.Shutdown();
		}
	}

	public void StartupWorkerThreads()
	{
		foreach (List<WorkerThreadBase> workerThreadList in workerThreadLists)
		{
			foreach (WorkerThreadBase item in workerThreadList)
			{
				item.Startup();
			}
		}
	}

	public void ShutdownWorkerThreads()
	{
		foreach (List<WorkerThreadBase> workerThreadList in workerThreadLists)
		{
			foreach (WorkerThreadBase item in workerThreadList)
			{
				item.Shutdown();
			}
		}
	}

	public void SetCombinedScripter(CombinedScripter combinedScripter)
	{
		foreach (BuilderBase builder in builders)
		{
			builder.SetCombinedScripter(combinedScripter);
		}
	}

	public void SetDeviceListView(ListView listView)
	{
		foreach (BuilderBase builder in builders)
		{
			builder.SetDeviceListView(listView);
		}
	}

	public void ApplicationReady()
	{
		foreach (BuilderBase builder in builders)
		{
			builder.ApplicationReady();
		}
	}

	private bool LoadAndCheckLibrary(string filename)
	{
		try
		{
			Assembly assembly = Assembly.LoadFile(Path.GetFullPath(filename));
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.BaseType.FullName == "QCRPG.Framework.BuilderBase")
				{
					if (!validLibrariesLoaded.Contains(assembly))
					{
						validLibrariesLoaded.Add(assembly);
					}
					return true;
				}
			}
		}
		catch (Exception)
		{
		}
		return false;
	}

	private void CreateBuilders(bool deviceEmulationMode, bool commandLineMode, int dutNumber)
	{
		builders = new List<BuilderBase>();
		foreach (Assembly item in validLibrariesLoaded)
		{
			Type[] types = item.GetTypes();
			foreach (Type type in types)
			{
				if (!(type.BaseType.FullName == "QCRPG.Framework.BuilderBase"))
				{
					continue;
				}
				BuilderBase builderBase = (BuilderBase)Activator.CreateInstance(type);
				if (deviceEmulationMode)
				{
					if (!builderBase.DeviceEmulationModeIsSupported())
					{
						continue;
					}
					builderBase.BuildTSL(PacketReceiveMode.Asynchronous, deviceEmulationMode, dutNumber, commandLineMode);
				}
				else
				{
					builderBase.BuildTSL(PacketReceiveMode.Asynchronous, deviceEmulationMode, dutNumber, commandLineMode);
				}
				builders.Add(builderBase);
				technologyNames.Add(builderBase.Name);
				if (builderBase.Logger != null)
				{
					loggers.Add(builderBase.Logger);
				}
				if (builderBase.Configurer != null)
				{
					configurers.Add(builderBase.Configurer);
					if (!deviceEmulationMode)
					{
						configurerToFilenameMap.Add(builderBase.Configurer, item.Location + ".Config_DUT" + DUTNumber + ".Xml");
					}
					else
					{
						configurerToFilenameMap.Add(builderBase.Configurer, item.Location + ".Config_DUT" + DUTNumber + ".EmulationMode.Xml");
					}
				}
				if (builderBase.PacketList != null)
				{
					packetLists.Add(builderBase.PacketList);
				}
				if (builderBase.API != null)
				{
					apis.Add(builderBase.API);
				}
				if (builderBase.Gooier != null)
				{
					gooiers.Add(builderBase.Gooier);
				}
				if (builderBase.Scripter != null)
				{
					scripters.Add(builderBase.Scripter);
				}
				if (builderBase.WorkerThreads != null)
				{
					workerThreadLists.Add(builderBase.WorkerThreads);
				}
			}
		}
		if (!isDutSpecificStackAvailable)
		{
			return;
		}
		DUTSpecificBuilder dUTSpecificBuilder = new DUTSpecificBuilder();
		List<APIBase> apiList = new List<APIBase>(apis);
		dUTSpecificBuilder.BuildTSL(PacketReceiveMode.Asynchronous, deviceEmulationMode, dutNumber, commandLineMode, automationMode: false, apiList);
		foreach (APIBase api in apis)
		{
			if (api is CommonAPI)
			{
				((CommonAPI)api).setCommonStack((DUTSpecificAPI)dUTSpecificBuilder.API);
			}
		}
		builders.Add(dUTSpecificBuilder);
		technologyNames.Add(dUTSpecificBuilder.Name);
		if (dUTSpecificBuilder.Logger != null)
		{
			loggers.Add(dUTSpecificBuilder.Logger);
		}
		if (dUTSpecificBuilder.Configurer != null)
		{
			configurers.Add(dUTSpecificBuilder.Configurer);
		}
		if (dUTSpecificBuilder.PacketList != null)
		{
			packetLists.Add(dUTSpecificBuilder.PacketList);
		}
		if (dUTSpecificBuilder.API != null)
		{
			apis.Add(dUTSpecificBuilder.API);
		}
		if (dUTSpecificBuilder.Gooier != null)
		{
			gooiers.Add(dUTSpecificBuilder.Gooier);
		}
		dUTSpecificBuilder.Logger.Startup();
		CommonAPI.IsDutSpecificStackAvailable = true;
	}
}
