using System;
using System.Collections.Generic;
using QCRPG.Framework;
using QCRPG.TSL.FM.Packets;

namespace QCRPG.TSL.FM;

public class FMCustomSendPacketHandler
{
	private const int usTuneOffset = 87500;

	private const int japanTuneOffset = 76000;

	private const string dataTransferBitNotSetMessage = "Data transfer completed bit not set";

	private FMAPI fmAPI;

	private ReceivePacketHandlerBase receivePacketHandler;

	public FMCustomSendPacketHandler(FMAPI fmAPI, ReceivePacketHandlerBase receivePacketHandler)
	{
		this.fmAPI = fmAPI;
		this.receivePacketHandler = receivePacketHandler;
		fmAPI.SetCustomSendPacketHandler(typeof(RadioControl), RadioControlHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRdsDataGroup), ReadRdsDataGroupHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(RdsConfig), RdsConfigHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRdsProgramService), ReadRdsProgramServiceHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRdsRadioText), ReadRdsRadioTextHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRdsAlternativeFrequency), ReadRdsAlternativeFrequencyHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(RdsTransmitRadioText), RdsTransmitRadioTextHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(RdsTransmitProgramService), RdsTransmitProgramServiceHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadInterruptStatus), ReadInterruptStatusHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRadioControl), ReadRadioControlHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadTuneStatus), ReadTuneStatusHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadIoControl), ReadIoControlHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRdsControl), ReadRdsControlHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadAdvanceControl), ReadAdvanceControlHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadRmssiLevel), ReadRmssiLevelHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadI2c), ReadI2cHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(ReadI2cRegister), ReadI2cRegisterHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(BlockPoke), BlockPokeHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(BlockPeek), BlockPeekHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(MultiplePoke), MultiplePokeHandler);
		fmAPI.SetCustomSendPacketHandler(typeof(MultiplePeek), MultiplePeekHandler);
		TuneInfo.TuneOffset = 87500u;
	}

	private bool RadioControlHandler(PacketBase packet)
	{
		if (((RadioControl)packet).UserFields.GetBandAsBandEnum() == RadioControl.UserFieldsWrapper.BandEnum.US_AND_EUROPE)
		{
			TuneInfo.TuneOffset = 87500u;
		}
		else
		{
			TuneInfo.TuneOffset = 76000u;
		}
		return false;
	}

	private bool ReadRdsDataGroupHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 15u, 12u);
	}

	private bool RdsConfigHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: true, readAnotherRegister: false, 0u, 0u);
	}

	private bool ReadRdsProgramServiceHandler(PacketBase packet)
	{
		ReadRdsProgramService readRdsProgramService = (ReadRdsProgramService)packet;
		List<byte> list = new List<byte>();
		List<byte> list2 = new List<byte>();
		fmAPI.I2CWrite(readRdsProgramService.ToByteArray());
		CheckIntStatRegister();
		list.AddRange(ReadTransferredDataRegisters(5));
		int num = list[0] & 0xF;
		if (num > 12)
		{
			num = 12;
		}
		if (num > 0)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_1_READ, 16));
		}
		if (num > 2)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_2_READ, 16));
		}
		if (num > 4)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_3_READ, 16));
		}
		if (num > 6)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_4_READ, 16));
		}
		if (num > 8)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_5_READ, 16));
		}
		if (num > 10)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_PS_6_READ, 16));
		}
		list.AddRange(list2.GetRange(0, num * 8));
		ReadRdsProgramServiceResponse readRdsProgramServiceResponse = new ReadRdsProgramServiceResponse();
		if (!readRdsProgramServiceResponse.FromByteArray(list.ToArray()))
		{
			throw new Exception("Bytes are not a valid packet");
		}
		receivePacketHandler.EnqueuePacket(readRdsProgramServiceResponse);
		return true;
	}

	private bool ReadRdsRadioTextHandler(PacketBase packet)
	{
		ReadRdsRadioText readRdsRadioText = (ReadRdsRadioText)packet;
		List<byte> list = new List<byte>();
		List<byte> list2 = new List<byte>();
		fmAPI.I2CWrite(readRdsRadioText.ToByteArray());
		CheckIntStatRegister();
		list.AddRange(ReadTransferredDataRegisters(5));
		int num = list[0] & 0x7F;
		if (num > 64)
		{
			num = 64;
		}
		if (num > 0)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_RT_1_READ, 16));
		}
		if (num > 16)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_RT_2_READ, 16));
		}
		if (num > 32)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_RT_3_READ, 16));
		}
		if (num > 48)
		{
			list2.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_RT_4_READ, 16));
		}
		list.AddRange(list2.GetRange(0, num));
		ReadRdsRadioTextResponse readRdsRadioTextResponse = new ReadRdsRadioTextResponse();
		if (!readRdsRadioTextResponse.FromByteArray(list.ToArray()))
		{
			throw new Exception("Bytes are not a valid packet");
		}
		receivePacketHandler.EnqueuePacket(readRdsRadioTextResponse);
		return true;
	}

	private bool ReadRdsAlternativeFrequencyHandler(PacketBase packet)
	{
		ReadRdsAlternativeFrequency readRdsAlternativeFrequency = (ReadRdsAlternativeFrequency)packet;
		List<byte> list = new List<byte>();
		fmAPI.I2CWrite(readRdsAlternativeFrequency.ToByteArray());
		CheckIntStatRegister();
		list.AddRange(ReadTransferredDataRegisters(16));
		int num = list[4];
		if (num > 25)
		{
			num = 25;
		}
		if (num > 11)
		{
			list.AddRange(TransferAndReadData(XfrModeMapEnum.RDS_AF_1_READ, 16));
			list.RemoveRange(5 + num, 27 - num);
		}
		else
		{
			list.RemoveRange(5 + num, 11 - num);
		}
		ReadRdsAlternativeFrequencyResponse readRdsAlternativeFrequencyResponse = new ReadRdsAlternativeFrequencyResponse();
		if (!readRdsAlternativeFrequencyResponse.FromByteArray(list.ToArray()))
		{
			throw new Exception("Bytes are not a valid packet");
		}
		receivePacketHandler.EnqueuePacket(readRdsAlternativeFrequencyResponse);
		return true;
	}

	private bool RdsTransmitRadioTextHandler(PacketBase packet)
	{
		RdsTransmitRadioText rdsTransmitRadioText = (RdsTransmitRadioText)packet;
		List<byte> list = new List<byte>();
		list.AddRange(rdsTransmitRadioText.ToByteArray());
		int num = (int)rdsTransmitRadioText.UserFields.Length;
		if (num > 64)
		{
			num = 64;
		}
		for (int i = num; i < 64; i++)
		{
			list.Add(0);
		}
		byte[] data = list.ToArray();
		if (num > 0)
		{
			WriteTransferDataRegisters(data, 5, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_RT_1_WRITE);
			CheckIntStatRegister();
		}
		if (num > 16)
		{
			WriteTransferDataRegisters(data, 21, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_RT_2_WRITE);
			CheckIntStatRegister();
		}
		if (num > 32)
		{
			WriteTransferDataRegisters(data, 37, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_RT_3_WRITE);
			CheckIntStatRegister();
		}
		if (num > 48)
		{
			WriteTransferDataRegisters(data, 53, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_RT_4_WRITE);
			CheckIntStatRegister();
		}
		WriteTransferDataRegisters(data, 0, 5);
		WriteTransferControlRegisters(XfrModeMapEnum.RDS_RT_0_WRITE);
		CheckIntStatRegister();
		return true;
	}

	private bool RdsTransmitProgramServiceHandler(PacketBase packet)
	{
		RdsTransmitProgramService rdsTransmitProgramService = (RdsTransmitProgramService)packet;
		List<byte> list = new List<byte>();
		list.AddRange(rdsTransmitProgramService.ToByteArray());
		int num = (int)rdsTransmitProgramService.UserFields.NumberOfProgramServiceNames;
		if (num > 12)
		{
			num = 12;
		}
		for (int i = num; i < 12; i++)
		{
			byte[] collection = new byte[8];
			list.AddRange(collection);
		}
		byte[] data = list.ToArray();
		if (num > 0)
		{
			WriteTransferDataRegisters(data, 5, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_1_WRITE);
			CheckIntStatRegister();
		}
		if (num > 2)
		{
			WriteTransferDataRegisters(data, 21, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_2_WRITE);
			CheckIntStatRegister();
		}
		if (num > 4)
		{
			WriteTransferDataRegisters(data, 37, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_3_WRITE);
			CheckIntStatRegister();
		}
		if (num > 6)
		{
			WriteTransferDataRegisters(data, 53, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_4_WRITE);
			CheckIntStatRegister();
		}
		if (num > 8)
		{
			WriteTransferDataRegisters(data, 69, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_5_WRITE);
			CheckIntStatRegister();
		}
		if (num > 10)
		{
			WriteTransferDataRegisters(data, 85, 16);
			WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_6_WRITE);
			CheckIntStatRegister();
		}
		WriteTransferDataRegisters(data, 0, 5);
		WriteTransferControlRegisters(XfrModeMapEnum.RDS_PS_0_WRITE);
		CheckIntStatRegister();
		return true;
	}

	private bool ReadInterruptStatusHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 0u, 3u);
	}

	private bool ReadRadioControlHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 3u, 1u);
	}

	private bool ReadTuneStatusHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 4u, 2u);
	}

	private bool ReadIoControlHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 9u, 1u);
	}

	private bool ReadRdsControlHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 10u, 1u);
	}

	private bool ReadAdvanceControlHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 11u, 1u);
	}

	private bool ReadRmssiLevelHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: false, readAnotherRegister: true, 13u, 1u);
	}

	private bool ReadI2cHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: true, 0, checkIntStatRegister: false, readAnotherRegister: false, 0u, ((ReadI2c)packet).UserFields.Length);
	}

	private bool ReadI2cRegisterHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: true, 0, checkIntStatRegister: false, readAnotherRegister: true, ((ReadI2cRegister)packet).UserFields.RegisterAddress, ((ReadI2cRegister)packet).UserFields.Length);
	}

	private bool BlockPokeHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: true, readAnotherRegister: false, 0u, 0u);
	}

	private bool BlockPeekHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: true, readAnotherRegister: true, RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.XFRDAT0), ((BlockPeek)packet).UserFields.Length);
	}

	private bool MultiplePokeHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: true, readAnotherRegister: false, 0u, 0u);
	}

	private bool MultiplePeekHandler(PacketBase packet)
	{
		return CommonSimpleHandler(packet, alterWriteCount: false, 0, checkIntStatRegister: true, readAnotherRegister: true, RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.XFRDAT0), ((MultiplePeek)packet).UserFields.Length);
	}

	private bool CommonSimpleHandler(PacketBase packet, bool alterWriteCount, int writeCount, bool checkIntStatRegister, bool readAnotherRegister, uint readAnotherRegisterAddress, uint readLength)
	{
		if (!alterWriteCount)
		{
			byte[] array = packet.ToByteArray();
			if (array.Length > 0)
			{
				fmAPI.I2CWrite(array);
			}
		}
		else if (writeCount > 0)
		{
			fmAPI.I2CWrite(packet.ToByteArray(), writeCount);
		}
		if (checkIntStatRegister)
		{
			CheckIntStatRegister();
		}
		if (readAnotherRegister)
		{
			fmAPI.I2CRead((byte)readAnotherRegisterAddress, (byte)readLength);
		}
		else if (readLength != 0)
		{
			fmAPI.I2CRead((byte)readLength);
		}
		return true;
	}

	private void CheckIntStatRegister()
	{
		byte[] array = fmAPI.I2CRead((byte)RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.INTSTAT1), 3, skipReceiveEnqueue: true);
		if ((array[2] & 1) != 1)
		{
			throw new Exception("Data transfer completed bit not set");
		}
	}

	private void WriteTransferControlRegisters(XfrModeMapEnum xfrMode)
	{
		byte b = (byte)RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.XFRCTRL);
		byte b2 = (byte)XfrModeMapInfo.XfrModeMapToValue(xfrMode);
		fmAPI.I2CWrite(new byte[2] { b, b2 });
	}

	private void WriteTransferDataRegisters(byte[] data, int index, int length)
	{
		byte registerAddress = (byte)RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.XFRDAT0);
		List<byte> list = new List<byte>();
		for (int i = 0; i < length; i++)
		{
			list.Add(data[i + index]);
		}
		fmAPI.I2CWrite(registerAddress, list.ToArray());
	}

	private byte[] ReadTransferredDataRegisters(byte length)
	{
		byte registerAddress = (byte)RegisterMapInfo.RegisterMapToValue(RegisterMapEnum.XFRDAT0);
		return fmAPI.I2CRead(registerAddress, length, skipReceiveEnqueue: true);
	}

	private byte[] TransferAndReadData(XfrModeMapEnum xfrMode, byte length)
	{
		WriteTransferControlRegisters(xfrMode);
		CheckIntStatRegister();
		return ReadTransferredDataRegisters(length);
	}
}
