using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace QCRPG.Framework;

public static class Conversions
{
	private static Dictionary<string, string> xmlStringToEscapeMap;

	private static Dictionary<string, string> xmlEscapeToStringMap;

	static Conversions()
	{
		xmlStringToEscapeMap = new Dictionary<string, string>();
		xmlEscapeToStringMap = new Dictionary<string, string>();
		xmlStringToEscapeMap.Add("&", "&amp;");
		xmlStringToEscapeMap.Add("\"", "&quot;");
		xmlStringToEscapeMap.Add("'", "&apos;");
		xmlStringToEscapeMap.Add("<", "&lt;");
		xmlStringToEscapeMap.Add(">", "&gt;");
		xmlEscapeToStringMap.Add("&amp;", "&");
		xmlEscapeToStringMap.Add("&quot;", "\"");
		xmlEscapeToStringMap.Add("&apos;", "'");
		xmlEscapeToStringMap.Add("&lt;", "<");
		xmlEscapeToStringMap.Add("&gt;", ">");
	}

	public static string ByteToHexString(byte b)
	{
		return b.ToString("X2");
	}

	public static byte HexStringToByte(string s)
	{
		if (s.Length < 1 || s.Length > 2)
		{
			throw new Exception("Invalid string length");
		}
		return Convert.ToByte(s, 16);
	}

	public static uint HexStringToUint(string s)
	{
		if (s.Length < 1 || s.Length > 8)
		{
			throw new Exception("Invalid string length");
		}
		return Convert.ToUInt32(s, 16);
	}

	public static string ByteArrayToHexString(byte[] byteArray)
	{
		if (byteArray == null)
		{
			return "";
		}
		return ByteArrayToHexString(byteArray, byteArray.Length);
	}

	public static byte[] HexStringToByteArray(string s)
	{
		if (s.Length % 2 != 0)
		{
			throw new Exception("Invalid string length");
		}
		byte[] array = new byte[s.Length / 2];
		int num = 0;
		int num2 = 0;
		while (num < s.Length)
		{
			array[num2] = Convert.ToByte(s.Substring(num, 2), 16);
			num += 2;
			num2++;
		}
		return array;
	}

	public static string ByteArrayToHexString(byte[] byteArray, int length)
	{
		if (byteArray == null)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < length; i++)
		{
			stringBuilder.Append(ByteToHexString(byteArray[i]));
		}
		return stringBuilder.ToString().TrimEnd();
	}

	public static string ByteArrayTo0xHexString(byte[] byteArray, bool singlePrefix = false)
	{
		if (byteArray == null)
		{
			return "";
		}
		return ByteArrayTo0xHexString(byteArray, byteArray.Length, singlePrefix);
	}

	public static string ByteArrayTo0xHexString(byte[] byteArray, int length, bool singlePrefix = false)
	{
		if (byteArray == null)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		string text = "0x";
		string text2 = " ";
		if (singlePrefix)
		{
			stringBuilder.Append(text);
			text = (text2 = "");
		}
		for (int i = 0; i < length; i++)
		{
			stringBuilder.Append(text + ByteToHexString(byteArray[i]) + text2);
		}
		return stringBuilder.ToString().TrimEnd();
	}

	public static string ByteArrayToSpacedHexString(byte[] byteArray)
	{
		if (byteArray == null)
		{
			return "";
		}
		return ByteArrayToSpacedHexString(byteArray, byteArray.Length);
	}

	public static string ByteArrayToSpacedHexString(byte[] byteArray, int length)
	{
		if (byteArray == null)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < length; i++)
		{
			stringBuilder.Append(ByteToHexString(byteArray[i]) + " ");
		}
		return stringBuilder.ToString().TrimEnd();
	}

	public static byte[] ByteToHexAsciiByteArray(byte b)
	{
		byte[] array = new byte[2];
		byte b2 = (byte)((b & 0xF0) >> 4);
		byte b3 = (byte)(b & 0xFu);
		if (b2 >= 0 && b2 <= 9)
		{
			array[0] = (byte)(b2 | 0x30u);
		}
		else
		{
			array[0] = (byte)(b2 + 55);
		}
		if (b3 >= 0 && b3 <= 9)
		{
			array[1] = (byte)(b3 | 0x30u);
		}
		else
		{
			array[1] = (byte)(b3 + 55);
		}
		return array;
	}

	public static byte[] ByteArrayToHexAsciiByteArray(byte[] byteArray)
	{
		if (byteArray == null)
		{
			return new byte[0];
		}
		return ByteArrayToHexAsciiByteArray(byteArray, byteArray.Length);
	}

	public static byte[] ByteArrayToHexAsciiByteArray(byte[] byteArray, int length)
	{
		if (byteArray == null)
		{
			return new byte[0];
		}
		byte[] array = new byte[length * 2];
		for (int i = 0; i < length; i++)
		{
			byte[] array2 = ByteToHexAsciiByteArray(byteArray[i]);
			array[i * 2] = array2[0];
			array[i * 2 + 1] = array2[1];
		}
		return array;
	}

	public static byte HexAsciiBytesToByte(byte leftNibble, byte rightNibble)
	{
		if (leftNibble >= 48 && leftNibble <= 57)
		{
			leftNibble = (byte)(leftNibble & 0xFu);
		}
		else if (leftNibble >= 65 && leftNibble <= 70)
		{
			leftNibble -= 55;
		}
		else
		{
			if (leftNibble < 97 || leftNibble > 102)
			{
				throw new Exception("Invalid byte: " + leftNibble);
			}
			leftNibble -= 87;
		}
		if (rightNibble >= 48 && rightNibble <= 57)
		{
			rightNibble = (byte)(rightNibble & 0xFu);
		}
		else if (rightNibble >= 65 && rightNibble <= 70)
		{
			rightNibble -= 55;
		}
		else
		{
			if (rightNibble < 97 || rightNibble > 102)
			{
				throw new Exception("Invalid byte: " + rightNibble);
			}
			rightNibble -= 87;
		}
		return (byte)((leftNibble << 4) | rightNibble);
	}

	public static byte[] HexAsciiByteArrayToByteArray(byte[] hexAsciiByteArray)
	{
		if (hexAsciiByteArray == null)
		{
			return new byte[0];
		}
		return HexAsciiByteArrayToByteArray(hexAsciiByteArray, hexAsciiByteArray.Length);
	}

	public static byte[] HexAsciiByteArrayToByteArray(byte[] hexAsciiByteArray, int length)
	{
		if (hexAsciiByteArray == null)
		{
			return new byte[0];
		}
		if (length % 2 != 0)
		{
			throw new Exception("Invalid length: " + length);
		}
		byte[] array = new byte[length / 2];
		for (int i = 0; i < length; i += 2)
		{
			array[i / 2] = HexAsciiBytesToByte(hexAsciiByteArray[i], hexAsciiByteArray[i + 1]);
		}
		return array;
	}

	public static string ByteArrayToString(byte[] byteArray)
	{
		return Encoding.UTF8.GetString(byteArray);
	}

	public static byte[] StringToByteArray(string s)
	{
		return Encoding.UTF8.GetBytes(s);
	}

	public static int PrefixedStringToInt(string s, int defaultBase = 10)
	{
		if (s.StartsWith("0x"))
		{
			s = s.Remove(0, 2);
			return Convert.ToInt32(s, 16);
		}
		if (s.StartsWith("0o"))
		{
			s = s.Remove(0, 2);
			return Convert.ToInt32(s, 8);
		}
		if (s.StartsWith("0b"))
		{
			s = s.Remove(0, 2);
			return Convert.ToInt32(s, 2);
		}
		return Convert.ToInt32(s, defaultBase);
	}

	public static byte PrefixedStringToByte(string s, int defaultBase = 10)
	{
		if (s.StartsWith("0x"))
		{
			s = s.Remove(0, 2);
			return Convert.ToByte(s, 16);
		}
		if (s.StartsWith("0o"))
		{
			s = s.Remove(0, 2);
			return Convert.ToByte(s, 8);
		}
		if (s.StartsWith("0b"))
		{
			s = s.Remove(0, 2);
			return Convert.ToByte(s, 2);
		}
		return Convert.ToByte(s, defaultBase);
	}

	public static List<byte[]> ChunkByteArray(byte[] byteArray, int maxChunkLength)
	{
		if (maxChunkLength < 1)
		{
			throw new Exception("Invalid max chunk length: " + maxChunkLength);
		}
		List<byte[]> list = new List<byte[]>();
		int num = 0;
		int num2 = byteArray.Length;
		int num3 = maxChunkLength;
		while (num2 > 0)
		{
			if (num2 < maxChunkLength)
			{
				num3 = num2;
			}
			byte[] array = new byte[num3];
			Array.Copy(byteArray, num, array, 0, num3);
			list.Add(array);
			num += num3;
			num2 -= num3;
		}
		return list;
	}

	public static string GenericArrayToString<T>(Array array)
	{
		StringBuilder stringBuilder = new StringBuilder();
		foreach (T item in array)
		{
			stringBuilder.AppendLine(item.ToString());
		}
		return stringBuilder.ToString();
	}

	public static byte[] ObjectToByteArray(object o)
	{
		if (o == null)
		{
			return null;
		}
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		MemoryStream memoryStream = new MemoryStream();
		binaryFormatter.Serialize(memoryStream, o);
		return memoryStream.ToArray();
	}

	public static object ByteArrayToObject(byte[] byteArray)
	{
		if (byteArray == null)
		{
			return null;
		}
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		MemoryStream serializationStream = new MemoryStream(byteArray);
		return binaryFormatter.Deserialize(serializationStream);
	}

	public static char ByteToPrintableChar(byte b)
	{
		if (b < 32)
		{
			return '.';
		}
		if (b > 126)
		{
			return '.';
		}
		return (char)b;
	}

	public static string ByteArrayToPrintableString(byte[] ba)
	{
		if (ba == null)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		foreach (byte b in ba)
		{
			stringBuilder.Append(ByteToPrintableChar(b));
		}
		return stringBuilder.ToString();
	}

	public static byte[] UintListToByteArray(List<uint> uintList, int startingElement = 0)
	{
		List<byte> list = new List<byte>();
		for (int i = startingElement; i < uintList.Count; i++)
		{
			uint num = uintList[i];
			if (num > 255)
			{
				throw new Exception("Encountered value greater than 0xFF");
			}
			list.Add((byte)(num & 0xFFu));
		}
		return list.ToArray();
	}

	public static uint UintListToUint(List<uint> uintList, int startingElement = 0, bool elementZeroIsMsb = true)
	{
		byte[] array = UintListToByteArray(uintList, startingElement);
		return ByteArrayToUint(array, 0, array.Length, elementZeroIsMsb);
	}

	public static string StringToXmlEscapedString(string s)
	{
		foreach (string key in xmlStringToEscapeMap.Keys)
		{
			s = s.Replace(key, xmlStringToEscapeMap[key]);
		}
		return s;
	}

	public static string XmlEscapedStringToString(string s)
	{
		foreach (string key in xmlEscapeToStringMap.Keys)
		{
			s = s.Replace(key, xmlEscapeToStringMap[key]);
		}
		return s;
	}

	public static uint ByteArrayToUint(byte[] byteArray, int length, bool elementZeroIsMsb)
	{
		return ByteArrayToUint(byteArray, 0, length, elementZeroIsMsb);
	}

	public static uint ByteArrayToUint(byte[] byteArray, int start, int length, bool elementZeroIsMsb)
	{
		if (length < 0 || length > 4)
		{
			throw new Exception("Invalid length: " + length);
		}
		uint num = 0u;
		if (elementZeroIsMsb)
		{
			if (length == 0)
			{
				return num;
			}
			num |= (uint)(byteArray[start] << 24);
			if (length == 1)
			{
				return num;
			}
			num |= (uint)(byteArray[start + 1] << 16);
			if (length == 2)
			{
				return num;
			}
			num |= (uint)(byteArray[start + 2] << 8);
			if (length == 3)
			{
				return num;
			}
			return num | byteArray[start + 3];
		}
		if (length == 0)
		{
			return num;
		}
		num |= byteArray[start];
		if (length == 1)
		{
			return num;
		}
		num |= (uint)(byteArray[start + 1] << 8);
		if (length == 2)
		{
			return num;
		}
		num |= (uint)(byteArray[start + 2] << 16);
		if (length == 3)
		{
			return num;
		}
		return num | (uint)(byteArray[start + 3] << 24);
	}
}
