using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Decal.Adapter.NetParser;
using Decal.Interop.Net;

namespace Decal.Adapter;

public class Message : MessageStruct
{
	private static Dictionary<int, MemberParser> mRecv;

	private static Dictionary<int, MemberParser> mSend;

	private static Dictionary<string, MemberParser> mTypes;

	private int mType;

	internal MessageStruct mStruct;

	public int Type => mType;

	public override int Count => mStruct.Count;

	public override object this[int index] => mStruct[index];

	public override object this[string name] => mStruct[name];

	public override byte[] RawData => mStruct.RawData;

	public override object Next => mStruct.Next;

	public override MessageStruct Parent => mStruct.Parent;

	internal Message()
	{
	}

	internal Message(IMessage2 msg, MessageDirection dir)
	{
		mType = BitConverter.ToInt32(msg.RawData, 0);
		mStruct = new MessageStruct(msg.RawData, 4, GetParser(mType, dir));
	}

	internal Message(byte[] Data, MemberParser Parser)
	{
		mType = BitConverter.ToInt32(Data, 0);
		mStruct = new MessageStruct(Data, 4, Parser);
	}

	internal Message(Message Source)
	{
		mType = Source.mType;
		mStruct = Source.mStruct;
	}

	internal static MemberParser GetParser(int type, MessageDirection dir)
	{
		MemberParser result = null;
		switch (dir)
		{
		case MessageDirection.Inbound:
			if (mRecv.ContainsKey(type))
			{
				result = mRecv[type];
			}
			break;
		case MessageDirection.Outbound:
			if (mSend.ContainsKey(type))
			{
				result = mSend[type];
			}
			break;
		}
		return result;
	}

	public override string Name(int index)
	{
		return mStruct.Name(index);
	}

	public override string Name(string memberName)
	{
		return mStruct.Name(memberName);
	}

	public override MessageStruct Struct(int index)
	{
		return mStruct.Struct(index);
	}

	public override MessageStruct Struct(string name)
	{
		return mStruct.Struct(name);
	}

	public override FieldType Value<FieldType>(int index)
	{
		return mStruct.Value<FieldType>(index);
	}

	public override FieldType Value<FieldType>(string name)
	{
		return mStruct.Value<FieldType>(name);
	}

	public override byte[] RawValue(int index)
	{
		return mStruct.RawValue(index);
	}

	public override byte[] RawValue(string name)
	{
		return mStruct.RawValue(name);
	}

	internal static void Initialize(string xmlFile)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		mRecv = new Dictionary<int, MemberParser>();
		mSend = new Dictionary<int, MemberParser>();
		mTypes = new Dictionary<string, MemberParser>();
		XmlDocument val = new XmlDocument();
		val.Load(xmlFile);
		foreach (XmlNode item in ((XmlNode)val).SelectNodes("/schema/datatypes/type"))
		{
			ParseType(item, val);
		}
		foreach (XmlNode item2 in ((XmlNode)val).SelectNodes("/schema/messages/message"))
		{
			ParseMessage(item2, val);
		}
	}

	private static void ParseType(XmlNode node, XmlDocument doc)
	{
		XmlAttribute val = node.Attributes["name"];
		if (val == null)
		{
			return;
		}
		string value = ((XmlNode)val).Value;
		if (mTypes.ContainsKey(value))
		{
			return;
		}
		MemberParser memberParser = new MemberParser();
		mTypes.Add(value, memberParser);
		val = node.Attributes["primitive"];
		if (val != null && string.Compare(((XmlNode)val).Value, "true", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
		{
			if (string.Compare(value, "BYTE", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.BYTE;
			}
			else if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.WORD;
			}
			else if (string.Compare(value, "PackedWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.PackedWORD;
			}
			else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.DWORD;
			}
			else if (string.Compare(value, "PackedDWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.PackedDWORD;
			}
			else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.QWORD;
			}
			else if (string.Compare(value, "float", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.@float;
			}
			else if (string.Compare(value, "double", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.@double;
			}
			else if (string.Compare(value, "String", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.String;
			}
			else if (string.Compare(value, "WString", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser.MemberType = MemberParserType.WString;
			}
		}
		else
		{
			memberParser.MemberType = MemberParserType.Struct;
			memberParser.Child = ParseStruct(node.ChildNodes, doc);
		}
	}

	private static void ParseMessage(XmlNode node, XmlDocument doc)
	{
		XmlAttribute val = node.Attributes["type"];
		if (val == null)
		{
			return;
		}
		string text = ((XmlNode)val).Value;
		if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
		{
			text = text.Substring(2);
		}
		int key = int.Parse(text, NumberStyles.HexNumber);
		bool flag = true;
		bool flag2 = false;
		val = node.Attributes["direction"];
		if (val != null)
		{
			if (string.Compare(((XmlNode)val).Value, "outbound", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				flag = false;
				flag2 = true;
			}
			else if (string.Compare(((XmlNode)val).Value, "both", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				flag2 = true;
			}
		}
		if ((flag && !mRecv.ContainsKey(key)) || (flag2 && !mSend.ContainsKey(key)))
		{
			MemberParser value = ParseStruct(node.ChildNodes, doc);
			if (flag && !mRecv.ContainsKey(key))
			{
				mRecv.Add(key, value);
			}
			if (flag2 && !mSend.ContainsKey(key))
			{
				mSend.Add(key, value);
			}
		}
	}

	private static MemberParser ParseStruct(XmlNodeList nodes, XmlDocument doc)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		MemberParser memberParser = new MemberParser();
		MemberParser memberParser2 = memberParser;
		int count = nodes.Count;
		for (int i = 0; i < count; i++)
		{
			XmlNode val = nodes[i];
			if ((int)val.NodeType != 1)
			{
				continue;
			}
			string name = val.Name;
			if (string.Compare(name, "field", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				XmlAttribute val2 = val.Attributes["type"];
				if (val2 != null)
				{
					string value = ((XmlNode)val2).Value;
					if (!mTypes.ContainsKey(value))
					{
						ParseType(((XmlNode)doc).SelectSingleNode("/schema/datatypes/type[@name='" + value + "']"), doc);
					}
					memberParser2.Next = new MemberParser(mTypes[value]);
					memberParser2 = memberParser2.Next;
					memberParser2.MemberName = ((XmlNode)val.Attributes["name"]).Value;
				}
			}
			else if (string.Compare(name, "maskmap", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				XmlAttribute val2 = val.Attributes["xor"];
				long conditionXor = 0L;
				string value;
				if (val2 != null)
				{
					value = ((XmlNode)val2).Value;
					if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
					{
						value = value.Substring(2);
					}
					conditionXor = long.Parse(value, NumberStyles.HexNumber);
				}
				value = ((XmlNode)val.Attributes["name"]).Value;
				memberParser2.Next = ParseMaskMap(val.ChildNodes, doc);
				while (memberParser2.Next != null)
				{
					memberParser2 = memberParser2.Next;
					memberParser2.Condition = MemberParserCondition.NE;
					memberParser2.ConditionResult = 0L;
					memberParser2.ConditionField = value;
					memberParser2.ConditionXor = conditionXor;
				}
			}
			else if (string.Compare(name, "switch", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				string value = ((XmlNode)val.Attributes["name"]).Value;
				XmlAttribute val2 = val.Attributes["mask"];
				long conditionXor = -1L;
				if (val2 != null)
				{
					value = ((XmlNode)val2).Value;
					if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
					{
						value = value.Substring(2);
					}
					conditionXor = long.Parse(value, NumberStyles.HexNumber);
				}
				memberParser2.Next = ParseSwitch(val.ChildNodes, doc);
				while (memberParser2.Next != null)
				{
					memberParser2 = memberParser2.Next;
					memberParser2.Condition = MemberParserCondition.EQ;
					memberParser2.ConditionField = value;
					memberParser2.ConditionAnd = conditionXor;
				}
			}
			else if (string.Compare(name, "vector", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				memberParser2.Next = new MemberParser();
				memberParser2 = memberParser2.Next;
				memberParser2.MemberType = MemberParserType.Vector;
				memberParser2.MemberName = ((XmlNode)val.Attributes["name"]).Value;
				memberParser2.LengthField = ((XmlNode)val.Attributes["length"]).Value;
				XmlAttribute val2 = val.Attributes["mask"];
				long conditionXor = -1L;
				if (val2 != null)
				{
					string value = ((XmlNode)val2).Value;
					if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
					{
						value = value.Substring(2);
					}
					conditionXor = long.Parse(value, NumberStyles.HexNumber);
				}
				memberParser2.LengthMask = conditionXor;
				val2 = val.Attributes["skip"];
				int num = 0;
				if (val2 != null)
				{
					string value = ((XmlNode)val2).Value;
					if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
					{
						value = value.Substring(2);
					}
					num = int.Parse(value, NumberStyles.HexNumber);
				}
				memberParser2.LengthDelta = -num;
				memberParser2.Child = ParseStruct(val.ChildNodes, doc);
			}
			else if (string.Compare(name, "align", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
			{
				string value = ((XmlNode)val.Attributes["type"]).Value;
				if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
				{
					memberParser2.PostAlignment = 2;
				}
				else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
				{
					memberParser2.PostAlignment = 4;
				}
				else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
				{
					memberParser2.PostAlignment = 8;
				}
			}
		}
		if (memberParser.PostAlignment != 0 && memberParser.Next != null)
		{
			memberParser.Next.PreAlignment = memberParser.PostAlignment;
		}
		return memberParser.Next;
	}

	private static MemberParser ParseMaskMap(XmlNodeList nodes, XmlDocument doc)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		MemberParser memberParser = new MemberParser();
		MemberParser memberParser2 = memberParser;
		int count = nodes.Count;
		for (int i = 0; i < count; i++)
		{
			XmlNode val = nodes[i];
			if ((int)val.NodeType != 1 || string.Compare(val.Name, "mask", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
			{
				continue;
			}
			long conditionAnd = 0L;
			XmlAttribute val2 = val.Attributes["value"];
			if (val2 != null)
			{
				string text = ((XmlNode)val2).Value;
				if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
				{
					text = text.Substring(2);
				}
				conditionAnd = long.Parse(text, NumberStyles.HexNumber);
			}
			memberParser2.Next = new MemberParser();
			memberParser2 = memberParser2.Next;
			memberParser2.MemberType = MemberParserType.Case;
			memberParser2.ConditionAnd = conditionAnd;
			memberParser2.Child = ParseStruct(val.ChildNodes, doc);
		}
		return memberParser.Next;
	}

	private static MemberParser ParseSwitch(XmlNodeList nodes, XmlDocument doc)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		MemberParser memberParser = new MemberParser();
		MemberParser memberParser2 = memberParser;
		int count = nodes.Count;
		for (int i = 0; i < count; i++)
		{
			XmlNode val = nodes[i];
			if ((int)val.NodeType != 1 || string.Compare(val.Name, "case", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
			{
				continue;
			}
			long conditionResult = 0L;
			XmlAttribute val2 = val.Attributes["value"];
			if (val2 != null)
			{
				string text = ((XmlNode)val2).Value;
				if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
				{
					text = text.Substring(2);
				}
				conditionResult = long.Parse(text, NumberStyles.HexNumber);
			}
			memberParser2.Next = new MemberParser();
			memberParser2 = memberParser2.Next;
			memberParser2.MemberType = MemberParserType.Case;
			memberParser2.ConditionResult = conditionResult;
			memberParser2.Child = ParseStruct(val.ChildNodes, doc);
		}
		return memberParser.Next;
	}
}
