using System.Diagnostics;
using Decal.Interop.Net;

namespace Decal.Adapter.NetParser;

/// <summary>
/// IMessageIterator base implementation
/// </summary>
public class MessageRootImpl : MessageRoot, IMessageIterator
{
	protected MessageWrapper Wrapped;

	protected MessageStruct Data;

	protected int FieldIndex;

	protected const int Error = -1;

	public object Current => Data.Value<object>(FieldIndex);

	public string FieldName => Data.Name(FieldIndex);

	public int Index => FieldIndex;

	public IMessage Message => Wrapped;

	public MessageRoot NextObjectIndex
	{
		[DebuggerNonUserCode]
		get
		{
			if (FieldIndex < Data.mCount)
			{
				MessageMemberWrapper result = new MessageMemberWrapper(Data.Struct(FieldIndex), Wrapped);
				FieldIndex++;
				return result;
			}
			throw new COMHResultException(HResults.E_FAIL);
		}
	}

	protected MessageRootImpl()
	{
	}

	protected MessageRootImpl(MessageStruct data, MessageWrapper wrapper)
		: this()
	{
		Wrapped = wrapper;
		Data = data;
		if (!Data.mParsed)
		{
			Data.Parse();
		}
	}

	public void Reset()
	{
		FieldIndex = 0;
	}

	[DebuggerNonUserCode]
	private T GetNext<T>(string name)
	{
		FieldIndex = Data.IndexFromName(name);
		if (FieldIndex != -1)
		{
			return Data.Value<T>(FieldIndex);
		}
		throw new COMHResultException(HResults.E_FAIL);
	}

	[DebuggerNonUserCode]
	private T GetNext<T>(int index)
	{
		if (index >= 0 && index < Data.mCount)
		{
			FieldIndex = index;
			return Data.Value<T>(FieldIndex);
		}
		throw new COMHResultException(HResults.E_FAIL);
	}

	[DebuggerNonUserCode]
	public object get_Next(object vIndex)
	{
		return GetNext<object>(Data.ObjectToIndex(vIndex));
	}

	[DebuggerNonUserCode]
	public double get_NextFloat(string Name)
	{
		return GetNext<double>(Name);
	}

	[DebuggerNonUserCode]
	public int get_NextInt(string Name)
	{
		return GetNext<int>(Name);
	}

	[DebuggerNonUserCode]
	public MessageRoot get_NextObject(string Name)
	{
		FieldIndex = Data.IndexFromName(Name);
		if (FieldIndex != -1)
		{
			return new MessageMemberWrapper(Data.Struct(FieldIndex), Wrapped);
		}
		throw new COMHResultException(HResults.E_FAIL);
	}

	[DebuggerNonUserCode]
	public ulong get_NextQWord(string Name)
	{
		return GetNext<ulong>(Name);
	}

	[DebuggerNonUserCode]
	public string get_NextString(string Name)
	{
		return GetNext<string>(Name);
	}
}
