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

namespace QCRPG.TSL.ZigBee.Packets;

public class MlmeScanConfirmation : PacketBase
{
	public class UserFieldsWrapper
	{
		private const uint _EventCode = 40u;

		private uint _Packetlength;

		private uint _Protocolid;

		private uint _Length;

		private uint _Status;

		private uint _Scantype = 1u;

		private uint _Chpage;

		private uint _Unscannedchannels;

		private uint _Resultlistsize;

		private List<PandescriptorSubField> _PandescriptorList = new List<PandescriptorSubField>();

		public uint Packetlength
		{
			get
			{
				return _Packetlength;
			}
			set
			{
				_Packetlength = value;
			}
		}

		public uint Protocolid
		{
			get
			{
				return _Protocolid;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Protocolid is 0xFF");
				}
				_Protocolid = value;
			}
		}

		public uint EventCode => 40u;

		public uint Length
		{
			get
			{
				return _Length;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for Length is 0xFFFF");
				}
				_Length = value;
			}
		}

		public uint Status
		{
			get
			{
				return _Status;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Status is 0xFF");
				}
				_Status = value;
			}
		}

		public uint Scantype
		{
			get
			{
				return _Scantype;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Scantype is 0xFF");
				}
				if (MlmeScanTypeInfo.ValueToMlmeScanType(value) == MlmeScanTypeEnum.InvalidMlmeScanTypeValue)
				{
					throw new Exception("Invalid Scantype value");
				}
				_Scantype = value;
			}
		}

		public uint Chpage
		{
			get
			{
				return _Chpage;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Chpage is 0xFF");
				}
				_Chpage = value;
			}
		}

		public uint Unscannedchannels
		{
			get
			{
				return _Unscannedchannels;
			}
			set
			{
				_Unscannedchannels = value;
			}
		}

		public uint Resultlistsize
		{
			get
			{
				return _Resultlistsize;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Resultlistsize is 0xFF");
				}
				_Resultlistsize = value;
				while (_PandescriptorList.Count < _Resultlistsize)
				{
					_PandescriptorList.Add(new PandescriptorSubField());
				}
				while (_PandescriptorList.Count > _Resultlistsize)
				{
					_PandescriptorList.RemoveAt(_PandescriptorList.Count - 1);
				}
			}
		}

		public List<PandescriptorSubField> PandescriptorList => _PandescriptorList;

		public ProtocolIdEnum GetProtocolidAsProtocolIdEnum()
		{
			return ProtocolIdInfo.ValueToProtocolId(_Protocolid);
		}

		public void SetProtocolidAsProtocolIdEnum(ProtocolIdEnum enumItem)
		{
			Protocolid = ProtocolIdInfo.ProtocolIdToValue(enumItem);
		}

		public CommandOpcodeEnum GetEventCodeAsCommandOpcodeEnum()
		{
			return CommandOpcodeInfo.ValueToCommandOpcode(40u);
		}

		public ErrorCodeEnum GetStatusAsErrorCodeEnum()
		{
			return ErrorCodeInfo.ValueToErrorCode(_Status);
		}

		public void SetStatusAsErrorCodeEnum(ErrorCodeEnum enumItem)
		{
			Status = ErrorCodeInfo.ErrorCodeToValue(enumItem);
		}

		public MlmeScanTypeEnum GetScantypeAsMlmeScanTypeEnum()
		{
			return MlmeScanTypeInfo.ValueToMlmeScanType(_Scantype);
		}

		public void SetScantypeAsMlmeScanTypeEnum(MlmeScanTypeEnum enumItem)
		{
			Scantype = MlmeScanTypeInfo.MlmeScanTypeToValue(enumItem);
		}
	}

	public class PandescriptorSubField
	{
		private uint _Coordaddrmode = 2u;

		private uint _Coordpanid;

		private ulong _Coordaddress;

		private uint _Logicalchannel;

		private uint _Channelpage;

		private uint _Superframespec;

		private uint _Gtspermit;

		private uint _Linkquality;

		private uint _Timestamp;

		private uint _Securityfailure;

		private uint _Securitylevel;

		private uint _Keyidmode;

		private ulong _Keysource;

		private uint _Keyindex;

		public uint Coordaddrmode
		{
			get
			{
				return _Coordaddrmode;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Coordaddrmode is 0xFF");
				}
				_Coordaddrmode = value;
			}
		}

		public uint Coordpanid
		{
			get
			{
				return _Coordpanid;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for Coordpanid is 0xFFFF");
				}
				_Coordpanid = value;
			}
		}

		public ulong Coordaddress
		{
			get
			{
				return _Coordaddress;
			}
			set
			{
				_Coordaddress = value;
			}
		}

		public uint Logicalchannel
		{
			get
			{
				return _Logicalchannel;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Logicalchannel is 0xFF");
				}
				_Logicalchannel = value;
			}
		}

		public uint Channelpage
		{
			get
			{
				return _Channelpage;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Channelpage is 0xFF");
				}
				_Channelpage = value;
			}
		}

		public uint Superframespec
		{
			get
			{
				return _Superframespec;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for Superframespec is 0xFFFF");
				}
				_Superframespec = value;
			}
		}

		public uint Gtspermit
		{
			get
			{
				return _Gtspermit;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Gtspermit is 0xFF");
				}
				_Gtspermit = value;
			}
		}

		public uint Linkquality
		{
			get
			{
				return _Linkquality;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for Linkquality is 0xFFFF");
				}
				_Linkquality = value;
			}
		}

		public uint Timestamp
		{
			get
			{
				return _Timestamp;
			}
			set
			{
				_Timestamp = value;
			}
		}

		public uint Securityfailure
		{
			get
			{
				return _Securityfailure;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Securityfailure is 0xFF");
				}
				_Securityfailure = value;
			}
		}

		public uint Securitylevel
		{
			get
			{
				return _Securitylevel;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Securitylevel is 0xFF");
				}
				_Securitylevel = value;
			}
		}

		public uint Keyidmode
		{
			get
			{
				return _Keyidmode;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Keyidmode is 0xFF");
				}
				_Keyidmode = value;
			}
		}

		public ulong Keysource
		{
			get
			{
				return _Keysource;
			}
			set
			{
				_Keysource = value;
			}
		}

		public uint Keyindex
		{
			get
			{
				return _Keyindex;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for Keyindex is 0xFF");
				}
				_Keyindex = value;
			}
		}

		public void SetDefaultValues()
		{
			Coordaddrmode = 2u;
			Coordpanid = 0u;
			Securitylevel = 0u;
			Keyidmode = 0u;
			Keysource = 1312068706972498023uL;
			Keyindex = 1u;
		}

		public DutaddressmodeEnum GetCoordaddrmodeAsDutaddressmodeEnum()
		{
			return DutaddressmodeInfo.ValueToDutaddressmode(_Coordaddrmode);
		}

		public void SetCoordaddrmodeAsDutaddressmodeEnum(DutaddressmodeEnum enumItem)
		{
			Coordaddrmode = DutaddressmodeInfo.DutaddressmodeToValue(enumItem);
		}

		public SecurityLevelOptionsEnum GetSecuritylevelAsSecurityLevelOptionsEnum()
		{
			return SecurityLevelOptionsInfo.ValueToSecurityLevelOptions(_Securitylevel);
		}

		public void SetSecuritylevelAsSecurityLevelOptionsEnum(SecurityLevelOptionsEnum enumItem)
		{
			Securitylevel = SecurityLevelOptionsInfo.SecurityLevelOptionsToValue(enumItem);
		}

		public bool FromBitBuilder(ref BitBuilder bitBuilder)
		{
			Coordaddrmode = bitBuilder.RemoveBitsAsUint(8);
			Coordpanid = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			Coordaddress = bitBuilder.RemoveBitsAsUlongLittleEndian(64);
			Logicalchannel = bitBuilder.RemoveBitsAsUint(8);
			Channelpage = bitBuilder.RemoveBitsAsUint(8);
			Superframespec = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			Gtspermit = bitBuilder.RemoveBitsAsUint(8);
			Linkquality = bitBuilder.RemoveBitsAsUint(16);
			Timestamp = bitBuilder.RemoveBitsAsUintLittleEndian(32);
			Securityfailure = bitBuilder.RemoveBitsAsUint(8);
			Securitylevel = bitBuilder.RemoveBitsAsUint(8);
			Keyidmode = bitBuilder.RemoveBitsAsUint(8);
			Keysource = bitBuilder.RemoveBitsAsUlong(64);
			Keyindex = bitBuilder.RemoveBitsAsUint(8);
			return true;
		}

		public string ToBitString()
		{
			BitBuilder bitBuilder = new BitBuilder();
			bitBuilder.AddBitsAsUint(Coordaddrmode, 8);
			bitBuilder.AddBitsAsUintLittleEndian(Coordpanid, 16);
			bitBuilder.AddBitsAsUlongLittleEndian(Coordaddress, 64);
			bitBuilder.AddBitsAsUint(Logicalchannel, 8);
			bitBuilder.AddBitsAsUint(Channelpage, 8);
			bitBuilder.AddBitsAsUintLittleEndian(Superframespec, 16);
			bitBuilder.AddBitsAsUint(Gtspermit, 8);
			bitBuilder.AddBitsAsUint(Linkquality, 16);
			bitBuilder.AddBitsAsUintLittleEndian(Timestamp, 32);
			bitBuilder.AddBitsAsUint(Securityfailure, 8);
			bitBuilder.AddBitsAsUint(Securitylevel, 8);
			bitBuilder.AddBitsAsUint(Keyidmode, 8);
			bitBuilder.AddBitsAsUlong(Keysource, 64);
			bitBuilder.AddBitsAsUint(Keyindex, 8);
			return bitBuilder.ToString();
		}

		public List<string> GetWarnings()
		{
			List<string> list = new List<string>();
			if (Coordaddrmode < 2)
			{
				list.Add("Minimum allowed value for CoordAddrMode is 0x2");
			}
			if (Coordaddrmode > 3)
			{
				list.Add("Maximum allowed value for CoordAddrMode is 0x3");
			}
			if (Coordpanid < 0)
			{
				list.Add("Minimum allowed value for CoordPANId is 0x0");
			}
			if (Coordpanid > 65535)
			{
				list.Add("Maximum allowed value for CoordPANId is 0xFFFF");
			}
			if (Securitylevel < 0)
			{
				list.Add("Minimum allowed value for SecurityLevel is 0x0");
			}
			if (Securitylevel > 7)
			{
				list.Add("Maximum allowed value for SecurityLevel is 0x7");
			}
			if (Keyidmode < 0)
			{
				list.Add("Minimum allowed value for KeyIdMode is 0x0");
			}
			if (Keyidmode > 3)
			{
				list.Add("Maximum allowed value for KeyIdMode is 0x3");
			}
			return list;
		}
	}

	private Type[] expectedResponseTypes = new Type[0];

	private PacketInfoBase info;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Response;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

	public override PacketInfoBase Info
	{
		get
		{
			if (info == null)
			{
				info = new MlmeScanConfirmationInfo(this);
			}
			return info;
		}
	}

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.Scantype = 1u;
		for (int i = 0; i < UserFields.PandescriptorList.Count; i++)
		{
			UserFields.PandescriptorList[i].SetDefaultValues();
		}
	}

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		UserFields.Packetlength = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.Protocolid = bitBuilder.RemoveBitsAsUint(8);
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.EventCode)
		{
			return false;
		}
		UserFields.Length = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.Status = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Scantype = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Chpage = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Unscannedchannels = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.Resultlistsize = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.PandescriptorList.Count; i++)
		{
			UserFields.PandescriptorList[i].FromBitBuilder(ref bitBuilder);
		}
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.Packetlength, 32);
		bitBuilder.AddBitsAsUint(UserFields.Protocolid, 8);
		bitBuilder.AddBitsAsUint(UserFields.EventCode, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.Length, 16);
		bitBuilder.AddBitsAsUint(UserFields.Status, 8);
		bitBuilder.AddBitsAsUint(UserFields.Scantype, 8);
		bitBuilder.AddBitsAsUint(UserFields.Chpage, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.Unscannedchannels, 32);
		bitBuilder.AddBitsAsUint(UserFields.Resultlistsize, 8);
		for (int i = 0; i < UserFields.PandescriptorList.Count; i++)
		{
			bitBuilder.AddBitsAsString(UserFields.PandescriptorList[i].ToBitString());
		}
		return bitBuilder.ToString();
	}

	public override List<string> GetWarnings()
	{
		List<string> list = new List<string>();
		if (UserFields.Scantype < 1)
		{
			list.Add("Minimum allowed value for ScanType is 0x1");
		}
		if (UserFields.Scantype > 3)
		{
			list.Add("Maximum allowed value for ScanType is 0x3");
		}
		for (int i = 0; i < UserFields.PandescriptorList.Count; i++)
		{
			list.AddRange(UserFields.PandescriptorList[i].GetWarnings());
		}
		return list;
	}
}
