using System;
using System.Collections.Generic;
using QCRPG.Framework;

namespace QCRPG.TSL.ZigBee;

public class ProtocolTABI : ProtocolBase
{
	private enum ReceiveState
	{
		NEW_PACKET,
		GETTING_COMPLETE_TABI_HEADER,
		GETTING_PACKET_LENGTH,
		CONFIRM_PROTOCOL_IDENTIFIER,
		GETTING_PACKET_IDENTIFIER,
		GETTING_PAYLOAD_LENGTH,
		GETTING_PAYLOAD
	}

	public const byte uartProtocolIDByteCommand = 1;

	public const byte uartProtocolIDByteEvent = 1;

	public const byte uartProtocolIDByteBTCommand = 1;

	public const byte uartProtocolIDByteBTEvent = 4;

	public byte[] uartTABIIDCommand = new byte[4] { 16, 0, 0, 0 };

	public byte[] uartTABI20IDCommand = new byte[4] { 32, 0, 0, 0 };

	public byte[] uartTABIIDEvent = new byte[4] { 16, 0, 0, 0 };

	public byte[] uartTABI20IDEvent = new byte[4] { 32, 0, 0, 0 };

	private List<byte> currentPacketReceived = new List<byte>();

	private ZigBeePacketDataType currentPacketTypeReceived;

	private int gotPacketProtocolIdentifier = 9;

	private int gotFullPacketLength = 2;

	private int gotFullTABIHEADER = 4;

	private int payloadLength;

	private int tabiConfirmationID = 4;

	private int tabiIndicationID = 2;

	private List<byte> incomingDataToSendAfterPostProcessing = new List<byte>();

	private GenericNotifier<IncomingPacketData> receiveDataNotifierPostProcessing = new GenericNotifier<IncomingPacketData>();

	private bool useBTProtocolIDBytes;

	public bool autoDetectProtocolIDByteToUse;

	private ReceiveState receiveState;

	public bool UseBTProtocolIDBytes
	{
		get
		{
			return useBTProtocolIDBytes;
		}
		set
		{
			if (!autoDetectProtocolIDByteToUse)
			{
				useBTProtocolIDBytes = value;
			}
		}
	}

	public bool AutoDetectProtocolIDByteToUse
	{
		get
		{
			return autoDetectProtocolIDByteToUse;
		}
		set
		{
			autoDetectProtocolIDByteToUse = value;
		}
	}

	public void Reset()
	{
		ClearCurrentPacket(notifyObserversAboutPostProcessingDataFirst: false);
		currentPacketTypeReceived = ZigBeePacketDataType.Raw;
		receiveState = ReceiveState.NEW_PACKET;
	}

	public override void Send(OutgoingPacketData packetData)
	{
		LogDebugLine("Got data to send out: " + Conversions.ByteArrayToHexString(packetData.bytes));
		OutgoingPacketData arg = AddUARTProtocolIDByte(packetData);
		sendDataNotifier.NotifyObservers(arg);
	}

	private OutgoingPacketData AddUARTProtocolIDByte(OutgoingPacketData packetData)
	{
		byte[] array = new byte[4] { 16, 0, 0, 0 };
		byte item = 1;
		if (!(packetData is ZigBeeOutgoingPacketData))
		{
			IncomingPacketData arg = new IncomingPacketData(PacketDataType.WarningMessage, "Got non-ZigBeeOutgoingPacketData, not adding UART protocol byte");
			receiveDataNotifier.NotifyObservers(arg);
			return packetData;
		}
		ZigBeeOutgoingPacketData zigBeeOutgoingPacketData = (ZigBeeOutgoingPacketData)packetData;
		if (zigBeeOutgoingPacketData.ZigBeePacketType == ZigBeePacketDataType.Raw)
		{
			return packetData;
		}
		if (zigBeeOutgoingPacketData.ZigBeePacketType == ZigBeePacketDataType.Command)
		{
			if (useBTProtocolIDBytes)
			{
				array = uartTABIIDCommand;
				item = 1;
			}
			else
			{
				array = uartTABIIDCommand;
				item = 1;
			}
		}
		else if (zigBeeOutgoingPacketData.ZigBeePacketType == ZigBeePacketDataType.Event)
		{
			array = ((!useBTProtocolIDBytes) ? uartTABIIDCommand : uartTABIIDCommand);
		}
		else if (zigBeeOutgoingPacketData.ZigBeePacketType == ZigBeePacketDataType.ResponseAsCommand)
		{
			if (useBTProtocolIDBytes)
			{
				array = uartTABIIDCommand;
				item = 3;
			}
			else
			{
				array = uartTABIIDCommand;
				item = 3;
			}
		}
		else if (zigBeeOutgoingPacketData.ZigBeePacketType == ZigBeePacketDataType.Tabi20Command)
		{
			array = ((!useBTProtocolIDBytes) ? uartTABI20IDCommand : uartTABI20IDCommand);
		}
		else
		{
			if (zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Event)
			{
				throw new Exception("Unsupported ZigBee packet type: " + zigBeeOutgoingPacketData.ZigBeePacketType);
			}
			array = ((!useBTProtocolIDBytes) ? uartTABI20IDCommand : uartTABI20IDCommand);
		}
		List<byte> list = new List<byte>();
		list.AddRange(array);
		int value = ((zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Command && zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Event) ? (packetData.bytes.Length + 1 + 2) : packetData.bytes.Length);
		byte[] bytes = BitConverter.GetBytes(value);
		list.AddRange(bytes);
		if (zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Command && zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Event)
		{
			list.Add(item);
		}
		list.Add(packetData.bytes[0]);
		if (zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Command && zigBeeOutgoingPacketData.ZigBeePacketType != ZigBeePacketDataType.Tabi20Event)
		{
			short value2 = (short)(packetData.bytes.Length - 1);
			bytes = BitConverter.GetBytes(value2);
			list.AddRange(bytes);
		}
		byte[] array2 = new byte[packetData.bytes.Length - 1];
		Array.Copy(packetData.bytes, 1, array2, 0, packetData.bytes.Length - 1);
		list.AddRange(array2);
		return new OutgoingPacketData(list.ToArray());
	}

	public override void NotifyObserver(IncomingPacketData packetData)
	{
		LogDebugLine("Got incoming packet data: " + Conversions.ByteArrayToHexString(packetData.bytes));
		if (packetData.type != 0)
		{
			receiveDataNotifier.NotifyObservers(packetData);
		}
		else
		{
			ReceiveWithProtocolIDCheck(packetData);
		}
	}

	private void ReceiveWithProtocolIDCheck(IncomingPacketData packetData)
	{
		for (int i = 0; i < packetData.bytes.Length; i++)
		{
			if (receiveState == ReceiveState.NEW_PACKET)
			{
				incomingDataToSendAfterPostProcessing.Add(packetData.bytes[i]);
				bool flag = true;
				if (autoDetectProtocolIDByteToUse)
				{
					if (packetData.bytes[i] == 1 || packetData.bytes[i] == 1)
					{
						useBTProtocolIDBytes = false;
					}
					else if (packetData.bytes[i] == 4 || packetData.bytes[i] == 1)
					{
						useBTProtocolIDBytes = true;
					}
				}
				if (packetData.bytes[i] == uartTABIIDEvent[0])
				{
					flag = false;
					currentPacketTypeReceived = ZigBeePacketDataType.Event;
					receiveState = ReceiveState.GETTING_COMPLETE_TABI_HEADER;
				}
				else if (packetData.bytes[i] == 1)
				{
					flag = false;
					currentPacketTypeReceived = ZigBeePacketDataType.Command;
					UpdatePacketParsingInfoAndReceiveState();
				}
				else if (useBTProtocolIDBytes)
				{
					if (packetData.bytes[i] == 4)
					{
						flag = false;
						currentPacketTypeReceived = ZigBeePacketDataType.Event;
						UpdatePacketParsingInfoAndReceiveState();
					}
					else if (packetData.bytes[i] == 1)
					{
						flag = false;
						currentPacketTypeReceived = ZigBeePacketDataType.Command;
						UpdatePacketParsingInfoAndReceiveState();
					}
				}
				if (packetData.bytes[i] == uartTABI20IDEvent[0])
				{
					flag = false;
					currentPacketTypeReceived = ZigBeePacketDataType.Tabi20Event;
					receiveState = ReceiveState.GETTING_COMPLETE_TABI_HEADER;
				}
				if (flag)
				{
					IncomingPacketData arg = new IncomingPacketData(PacketDataType.WarningMessage, "Unexpected protocol ID byte: 0x" + packetData.bytes[i].ToString("X2"));
					receiveDataNotifier.NotifyObservers(arg);
					ClearCurrentPacket(notifyObserversAboutPostProcessingDataFirst: true);
				}
			}
			else if (receiveState == ReceiveState.GETTING_COMPLETE_TABI_HEADER)
			{
				incomingDataToSendAfterPostProcessing.Add(packetData.bytes[i]);
				if (incomingDataToSendAfterPostProcessing.Count == gotFullTABIHEADER)
				{
					UpdatePacketParsingInfoAndReceiveState();
				}
			}
			else if (receiveState == ReceiveState.GETTING_PACKET_LENGTH)
			{
				currentPacketReceived.Add(packetData.bytes[i]);
				incomingDataToSendAfterPostProcessing.Add(packetData.bytes[i]);
				if (incomingDataToSendAfterPostProcessing.Count == gotFullPacketLength)
				{
					payloadLength = BitConverter.ToInt32(new byte[4]
					{
						incomingDataToSendAfterPostProcessing[gotFullPacketLength - 4],
						incomingDataToSendAfterPostProcessing[gotFullPacketLength - 3],
						incomingDataToSendAfterPostProcessing[gotFullPacketLength - 2],
						incomingDataToSendAfterPostProcessing[gotFullPacketLength - 1]
					}, 0);
					receiveState = ReceiveState.CONFIRM_PROTOCOL_IDENTIFIER;
				}
			}
			else if (receiveState == ReceiveState.CONFIRM_PROTOCOL_IDENTIFIER)
			{
				currentPacketReceived.Add(packetData.bytes[i]);
				if (currentPacketTypeReceived != ZigBeePacketDataType.Tabi20Event)
				{
					if (packetData.bytes[i] == tabiConfirmationID)
					{
						currentPacketTypeReceived = ZigBeePacketDataType.Event;
					}
					else if (packetData.bytes[i] == tabiIndicationID)
					{
						currentPacketTypeReceived = ZigBeePacketDataType.Indication;
					}
				}
				incomingDataToSendAfterPostProcessing.Add(packetData.bytes[i]);
				if (incomingDataToSendAfterPostProcessing.Count == gotPacketProtocolIdentifier)
				{
					receiveState = ReceiveState.GETTING_PAYLOAD;
				}
			}
			else
			{
				if (receiveState != ReceiveState.GETTING_PAYLOAD)
				{
					throw new Exception("Unsupported receive state: " + receiveState);
				}
				incomingDataToSendAfterPostProcessing.Add(packetData.bytes[i]);
				currentPacketReceived.Add(packetData.bytes[i]);
				if (currentPacketReceived.Count == payloadLength + 4)
				{
					HandleCompletePacket();
					ClearCurrentPacket(notifyObserversAboutPostProcessingDataFirst: true);
					receiveState = ReceiveState.NEW_PACKET;
				}
			}
		}
	}

	private void UpdatePacketParsingInfoAndReceiveState()
	{
		receiveState = ReceiveState.GETTING_PACKET_LENGTH;
		if (currentPacketTypeReceived == ZigBeePacketDataType.Event)
		{
			gotFullPacketLength = 8;
		}
		else if (currentPacketTypeReceived != ZigBeePacketDataType.Command)
		{
			if (currentPacketTypeReceived == ZigBeePacketDataType.Tabi20Event)
			{
				gotFullPacketLength = 8;
				return;
			}
			IncomingPacketData arg = new IncomingPacketData(PacketDataType.WarningMessage, "Unexpected packet type: " + currentPacketTypeReceived);
			receiveDataNotifier.NotifyObservers(arg);
			ClearCurrentPacket(notifyObserversAboutPostProcessingDataFirst: true);
			receiveState = ReceiveState.NEW_PACKET;
		}
	}

	public void RegisterReceiveDataObserverPostProcessing(QCRPG.Framework.IObserver<IncomingPacketData> observer)
	{
		receiveDataNotifierPostProcessing.RegisterObserver(observer);
	}

	public void UnregisterReceiveDataObserverPostProcessing(QCRPG.Framework.IObserver<IncomingPacketData> observer)
	{
		receiveDataNotifierPostProcessing.UnregisterObserver(observer);
	}

	private void HandleCompletePacket()
	{
		LogDebugLine("HandleCompletePacket()");
		IncomingPacketData arg = new IncomingPacketData(incomingDataToSendAfterPostProcessing.ToArray());
		receiveDataNotifierPostProcessing.NotifyObservers(arg);
		ZigBeeIncomingPacketData zigBeeIncomingPacketData = new ZigBeeIncomingPacketData(currentPacketReceived.ToArray());
		zigBeeIncomingPacketData.ZigBeePacketType = currentPacketTypeReceived;
		receiveDataNotifier.NotifyObservers(zigBeeIncomingPacketData);
		ClearCurrentPacket(notifyObserversAboutPostProcessingDataFirst: false);
		sendDataNotifier.NotifyObservers(new OutgoingPacketData(PacketDataType.Notification, 11));
	}

	private void ClearCurrentPacket(bool notifyObserversAboutPostProcessingDataFirst)
	{
		if (notifyObserversAboutPostProcessingDataFirst)
		{
			IncomingPacketData arg = new IncomingPacketData(incomingDataToSendAfterPostProcessing.ToArray());
			receiveDataNotifierPostProcessing.NotifyObservers(arg);
		}
		incomingDataToSendAfterPostProcessing.Clear();
		currentPacketReceived.Clear();
	}

	private void LogDebugLine(string line)
	{
	}
}
