using System.Collections.Generic;

namespace QCRPG.Framework;

public class CommonAPI : APIBase
{
	private static Dictionary<ConnectionBase, ConnectionSpecificApiInfo> connectionToConnectionSpecificApiInfoMap = new Dictionary<ConnectionBase, ConnectionSpecificApiInfo>();

	private DUTSpecificAPI dutSpecificApi;

	private static bool isDutSpecificStackAvailable = false;

	protected ProtocolCommon protocolCommon;

	protected ConnectionSpecificProtocolInfo connectionSpecificInfo;

	protected SnoopLogger snoopLog;

	protected SnoopLiveLogger snoopLiveLog;

	public static bool IsDutSpecificStackAvailable
	{
		get
		{
			return isDutSpecificStackAvailable;
		}
		set
		{
			isDutSpecificStackAvailable = value;
		}
	}

	public ConnectionSpecificProtocolInfo ConnectionSpecificInfo => connectionSpecificInfo;

	public CommonAPI(PacketListBase packetList, Logger logger, PacketReceiveMode packetReceiveMode)
		: base(packetList, logger, packetReceiveMode)
	{
		snoopLog = new SnoopLogger();
		snoopLiveLog = new SnoopLiveLogger();
	}

	public void setCommonStack(DUTSpecificAPI dutSpecificApi)
	{
		this.dutSpecificApi = dutSpecificApi;
	}

	public void AddSleepProtocolToSharedConnection(string portName)
	{
		APIBase.sharedConnectionManager.AddRoute(portName, 252, protocolCommon);
		APIBase.sharedConnectionManager.AddRoute(portName, 253, protocolCommon);
		APIBase.sharedConnectionManager.AddRoute(portName, 254, protocolCommon);
	}

	public ConnectionSpecificProtocolInfo.SleepModeState GetSleepMode()
	{
		if (connection != null && connection.IsOpen())
		{
			return protocolCommon.GetSleepMode();
		}
		if (connectionSpecificInfo == null)
		{
			connectionSpecificInfo = new ConnectionSpecificProtocolInfo();
		}
		return connectionSpecificInfo.SleepMode;
	}

	public virtual void SetSleepMode(ConnectionSpecificProtocolInfo.SleepModeState sleepMode)
	{
		if (connection != null && connection is ConnectionUsbBase && sleepMode != 0)
		{
			logger.NotifyObserver(new LogMessage(LogMessageType.Warning, string.Format("Sleep mode " + sleepMode.ToString() + " not supported for USB connection.")));
			return;
		}
		if (connectionSpecificInfo == null)
		{
			connectionSpecificInfo = new ConnectionSpecificProtocolInfo();
		}
		connectionSpecificInfo.SleepMode = sleepMode;
		if (protocolCommon != null)
		{
			protocolCommon.SetSleepMode(sleepMode);
		}
	}

	public virtual void EnableBTSnoopLogging(bool enabled, bool messagePopUp = true)
	{
	}

	public virtual bool SaveBTSnoopLogs(string fileName)
	{
		return false;
	}

	public virtual void ClearBTSnoopLogs()
	{
	}

	public virtual void EnableBTSnoopLiveLogging(bool enable, string BTSnoopLiveImportDllFileName, string BTSnoopLiveImportIniFileName)
	{
	}

	public virtual void CloseConnection()
	{
		removeConnectionSpecificApiInfo();
		protocolCommon.removeConnectionSpecificInfo();
	}

	protected override void ChangeConnection(ConnectionBase connection)
	{
		removeConnectionSpecificApiInfo();
		protocolCommon.removeConnectionSpecificInfo();
		if (isDutSpecificStackAvailable && dutSpecificApi != null && dutSpecificApi.ConnectionSpecificInfo != null)
		{
			connectionSpecificInfo = dutSpecificApi.ConnectionSpecificInfo;
		}
		else if (connectionSpecificInfo == null)
		{
			connectionSpecificInfo = new ConnectionSpecificProtocolInfo();
		}
		addConnectionSpecificApiInfo(connection, new ConnectionSpecificApiInfo());
		protocolCommon.addConnectionSpecificInfo(connection, connectionSpecificInfo);
		base.ChangeConnection(connection);
	}

	protected override void ChangeBottomProtocol(ProtocolBase protocol, bool usePacketDataReceiver = true)
	{
		base.ChangeBottomProtocol(protocol, usePacketDataReceiver);
		if (protocol != null && protocol is ProtocolCommon)
		{
			protocolCommon = (ProtocolCommon)protocol;
		}
	}

	protected override void ChangeTopProtocol(ProtocolBase protocol)
	{
		base.ChangeTopProtocol(protocol);
		if (protocol != null && protocol is ProtocolCommon)
		{
			protocolCommon = (ProtocolCommon)protocol;
		}
	}

	private void addConnectionSpecificApiInfo(ConnectionBase connection, ConnectionSpecificApiInfo connectionSpecificInfo)
	{
		if (connection == null)
		{
			return;
		}
		lock (connectionToConnectionSpecificApiInfoMap)
		{
			if (!connectionToConnectionSpecificApiInfoMap.ContainsKey(connection))
			{
				connectionToConnectionSpecificApiInfoMap.Add(connection, connectionSpecificInfo);
			}
		}
	}

	private void removeConnectionSpecificApiInfo()
	{
		if (connection == null)
		{
			return;
		}
		lock (connectionToConnectionSpecificApiInfoMap)
		{
			if (connectionToConnectionSpecificApiInfoMap.ContainsKey(connection))
			{
				connectionToConnectionSpecificApiInfoMap.Remove(connection);
			}
		}
	}

	private ConnectionSpecificApiInfo getDutSpecificState()
	{
		lock (connectionToConnectionSpecificApiInfoMap)
		{
			if (connection != null && connectionToConnectionSpecificApiInfoMap.ContainsKey(connection))
			{
				return connectionToConnectionSpecificApiInfoMap[connection];
			}
		}
		return null;
	}
}
