using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using QC.CTDS.DM.DataStructures;
using QC.CTDS.DM.DataStructures.PluginDataStructure;
using QC.CTDS.DM.SharedLibrary;

namespace QC.CTDS.DM.ApplicationsManager;

internal class PluginManager
{
	private List<InputPlugin> inputPluginsList = new List<InputPlugin>();

	private List<OutputPlugin> outputPluginsList = new List<OutputPlugin>();

	private List<AutoDescriptorPlugin> autoDescriptorPluginsList = new List<AutoDescriptorPlugin>();

	private List<PreDataTransformationPlugin> preDatatransformationPluginList = new List<PreDataTransformationPlugin>();

	internal List<InputPlugin> InputPluginsList
	{
		get
		{
			return inputPluginsList;
		}
		set
		{
			inputPluginsList = value;
		}
	}

	internal List<OutputPlugin> OutputPluginsList
	{
		get
		{
			return outputPluginsList;
		}
		set
		{
			outputPluginsList = value;
		}
	}

	public List<AutoDescriptorPlugin> AutoDescriptorPluginsList
	{
		get
		{
			return autoDescriptorPluginsList;
		}
		set
		{
			autoDescriptorPluginsList = value;
		}
	}

	public List<PreDataTransformationPlugin> PreDatatransformationPluginList
	{
		get
		{
			return preDatatransformationPluginList;
		}
		set
		{
			preDatatransformationPluginList = value;
		}
	}

	internal void LoadPlugins(string pluginsFolderPath)
	{
		if (string.IsNullOrEmpty(pluginsFolderPath))
		{
			pluginsFolderPath = Constants.PluginsFolderPath;
		}
		if (!Directory.Exists(pluginsFolderPath))
		{
			return;
		}
		DirectoryCatalog catalog = new DirectoryCatalog(pluginsFolderPath, "*.dll");
		CompositionContainer compositionContainer = new CompositionContainer(catalog);
		IEnumerable<InputPlugin> exportedValues = compositionContainer.GetExportedValues<InputPlugin>();
		IEnumerable<OutputPlugin> exportedValues2 = compositionContainer.GetExportedValues<OutputPlugin>();
		IEnumerable<AutoDescriptorPlugin> exportedValues3 = compositionContainer.GetExportedValues<AutoDescriptorPlugin>();
		IEnumerable<PreDataTransformationPlugin> exportedValues4 = compositionContainer.GetExportedValues<PreDataTransformationPlugin>();
		foreach (InputPlugin inputPlugin in exportedValues.OrderBy((InputPlugin plugin) => plugin.PluginName).ToList())
		{
			List<InputPlugin> source = InputPluginsList;
			Func<InputPlugin, bool> predicate = (InputPlugin plugin) => plugin.PluginName == inputPlugin.PluginName;
			if (!source.Any(predicate))
			{
				InputPluginsList.Add(inputPlugin);
				inputPlugin.OnMessageFromPlugin = MessageFromPlugin;
			}
		}
		foreach (OutputPlugin outputPlugin in exportedValues2.OrderBy((OutputPlugin plugin) => plugin.PluginName).ToList())
		{
			List<OutputPlugin> source2 = OutputPluginsList;
			Func<OutputPlugin, bool> predicate2 = (OutputPlugin plugin) => plugin.PluginName == outputPlugin.PluginName;
			if (!source2.Any(predicate2))
			{
				OutputPluginsList.Add(outputPlugin);
				outputPlugin.OnMessageFromPlugin = MessageFromPlugin;
			}
		}
		foreach (AutoDescriptorPlugin autoDescPlugin in exportedValues3.OrderBy((AutoDescriptorPlugin plugin) => plugin.PluginName).ToList())
		{
			List<AutoDescriptorPlugin> source3 = AutoDescriptorPluginsList;
			Func<AutoDescriptorPlugin, bool> predicate3 = (AutoDescriptorPlugin plugin) => plugin.PluginName == autoDescPlugin.PluginName;
			if (!source3.Any(predicate3))
			{
				AutoDescriptorPluginsList.Add(autoDescPlugin);
				autoDescPlugin.OnMessageFromPlugin = MessageFromPlugin;
			}
		}
		foreach (PreDataTransformationPlugin preTransform in exportedValues4.OrderBy((PreDataTransformationPlugin plugin) => plugin.PluginName).ToList())
		{
			List<PreDataTransformationPlugin> source4 = PreDatatransformationPluginList;
			Func<PreDataTransformationPlugin, bool> predicate4 = (PreDataTransformationPlugin plugin) => plugin.PluginName == preTransform.PluginName;
			if (!source4.Any(predicate4))
			{
				PreDatatransformationPluginList.Add(preTransform);
				preTransform.OnMessageFromPlugin = MessageFromPlugin;
			}
		}
	}

	internal void InitializePlugins()
	{
		PluginMessage pluginMessage = new PluginMessage();
		pluginMessage.MessageType = PluginMessageTypes.InitializePlugin;
		PluginMessage msg = pluginMessage;
		BroadcastMessageToAllPlugins(msg);
	}

	internal void BroadcastMessageToAllPlugins(PluginMessage msg)
	{
		InputPluginsList.ForEach(delegate(InputPlugin inputPlugin)
		{
			inputPlugin.MessageToPlugin(msg);
		});
		OutputPluginsList.ForEach(delegate(OutputPlugin inputPlugin)
		{
			inputPlugin.MessageToPlugin(msg);
		});
		AutoDescriptorPluginsList.ForEach(delegate(AutoDescriptorPlugin autoDescPlugin)
		{
			autoDescPlugin.MessageToPlugin(msg);
		});
	}

	internal void MessageFromPlugin(PluginMessage msg, string pluginName)
	{
		FindPlugin(pluginName)?.MessageToPlugin(msg);
	}

	private BasePlugin FindPlugin(string pluginName)
	{
		BasePlugin basePlugin = null;
		basePlugin = InputPluginsList.Find((InputPlugin plugin) => plugin.PluginName == pluginName);
		if (basePlugin != null)
		{
			return basePlugin;
		}
		basePlugin = OutputPluginsList.Find((OutputPlugin plugin) => plugin.PluginName == pluginName);
		if (basePlugin != null)
		{
			return basePlugin;
		}
		basePlugin = AutoDescriptorPluginsList.Find((AutoDescriptorPlugin plugin) => plugin.PluginName == pluginName);
		if (basePlugin != null)
		{
			return basePlugin;
		}
		basePlugin = PreDatatransformationPluginList.Find((PreDataTransformationPlugin plugin) => plugin.PluginName == pluginName);
		if (basePlugin != null)
		{
			return basePlugin;
		}
		return null;
	}

	internal void SetLogger(Action<string, LogType> WriteLog)
	{
		for (int i = 0; i < inputPluginsList.Count; i++)
		{
			inputPluginsList[i].OnWriteLog = WriteLog;
		}
		for (int j = 0; j < outputPluginsList.Count; j++)
		{
			outputPluginsList[j].OnWriteLog = WriteLog;
		}
		for (int k = 0; k < autoDescriptorPluginsList.Count; k++)
		{
			autoDescriptorPluginsList[k].OnWriteLog = WriteLog;
		}
		for (int l = 0; l < preDatatransformationPluginList.Count; l++)
		{
			preDatatransformationPluginList[l].OnWriteLog = WriteLog;
		}
	}
}
