using System;
using System.Runtime.InteropServices;

namespace QC.QMSLPhone;

public class LogAAGPSType3Measurement : LogMessage
{
	[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)]
	public struct LogAAGPSMeasurementHdrType3
	{
		public uint fcount;

		public ushort length;

		public byte version;

		public ulong reserved;

		public byte number_svs;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 38)]
	public struct LogAAGPSMeasurementType3
	{
		public byte sv_id;

		public byte health;

		public byte elevation;

		public byte azimuth;

		public short snr;

		public short cno;

		public ushort latency_ms;

		public byte pre_int;

		public ushort post_int;

		public uint millisecond;

		public uint sub_millisecond;

		public ushort sv_time_unc;

		public int sv_speed;

		public uint sv_speed_unc;

		public uint meas_status;

		public byte channel_state;

		public byte good_observations;

		public byte total_observations;

		public int reserved;
	}

	private const int hdrSize = 16;

	private const int recSize = 38;

	public LogAAGPSMeasurementHdrType3 ds;

	public LogAAGPSMeasurementType3[] dsSv = new LogAAGPSMeasurementType3[32];

	private GCHandle pinnedPacket;

	private IntPtr p;

	private IntPtr pAAGPSHdr;

	private IntPtr pAAGPS;

	public LogAAGPSType3Measurement(LogMessage msgVal)
		: base(msgVal.msgID, msgVal.message, displayRawVal: false)
	{
		message = msgVal.message;
		pinnedPacket = GCHandle.Alloc(message, GCHandleType.Pinned);
		p = pinnedPacket.AddrOfPinnedObject();
		pAAGPSHdr = new IntPtr(p.ToInt64() + 16);
		pAAGPS = new IntPtr(pAAGPSHdr.ToInt64() + 16);
		ds = (LogAAGPSMeasurementHdrType3)Marshal.PtrToStructure(pAAGPSHdr, typeof(LogAAGPSMeasurementHdrType3));
		for (int i = 0; i < ds.number_svs; i++)
		{
			IntPtr ptr = new IntPtr(pAAGPS.ToInt64() + i * 38);
			ref LogAAGPSMeasurementType3 reference = ref dsSv[i];
			reference = (LogAAGPSMeasurementType3)Marshal.PtrToStructure(ptr, typeof(LogAAGPSMeasurementType3));
		}
	}

	public double getCNO()
	{
		return getCNO(0);
	}

	public double getCNO(int numSV)
	{
		if (ds.number_svs > 0)
		{
			return (double)dsSv[numSV].cno / 10.0;
		}
		return 0.0;
	}

	public byte getGoodObsCnt()
	{
		return getGoodObsCnt(0);
	}

	public byte getGoodObsCnt(int numSV)
	{
		if (ds.number_svs > 0)
		{
			return dsSv[numSV].good_observations;
		}
		return 0;
	}

	public override string ToString()
	{
		string text = base.ToString() + $"FCount: {ds.fcount}";
		for (int i = 0; i < ds.number_svs; i++)
		{
			text = text + Environment.NewLine + $" SV: {dsSv[i].sv_id:00}" + $" CNO: {getCNO(i):0.00} ";
		}
		return text;
	}
}
