using System;

namespace DM2AE
{
	// 
	public class GDRE0
	{
		// 
		public class Entry
		{
			// 
			readonly byte[] pBinary;

			// 
			public Entry()
			{
				pBinary = new System.Byte[8];
			}
			// 
			public int Cat1
			{
				get { return pBinary[0]; }
			}
			// 
			public int Cat2
			{
				get { return pBinary[1]; }
			}
			// 
			public int Cat3
			{
				get { return pBinary[2]; }
			}
			// 
			public int Cat4
			{
				get { return pBinary[3]; }
			}
			// 
			public int Cat5
			{
				get { return pBinary[4]; }
			}
			// 
			public int Cat6
			{
				get { return pBinary[5]; }
			}
			// 
			public int BinIdx
			{
				get { return pBinary[6] * 256 + pBinary[7]; }
			}
			// 
			public System.Byte[] Binary
			{
				get { return pBinary; }
			}
		};
		// 
		public interface ETP
		{
			// 
			bool Test(byte x);
		}
		// 
		public class ETP_PASS : ETP
		{
			// 
			public bool Test(byte x)
			{
				return true;
			}
		}
		// 
		public class ETP_EQ : ETP
		{
			// 
			readonly byte nVal;

			// 
			public ETP_EQ(byte x)
			{
				nVal = x;
			}
			// 
			public bool Test(byte x)
			{
				return (nVal == x);
			}
		}
		// 
		public class ETP_NE : ETP
		{
			// 
			readonly byte nVal;

			// 
			public ETP_NE(byte x)
			{
				nVal = x;
			}
			// 
			public bool Test(byte x)
			{
				return (nVal != x);
			}
		}

		// 
		Entry[] pListEntries = null;
		// 
		System.Collections.SortedList pTextEN = null;
		// 
		System.Collections.SortedList pTextJA = null;
		// 
		bool fTextIsEn;

		// 
		public GDRE0()
		{

		}
		// 
		public bool Init(
			System.Byte[] pBinary,
			bool fLittleEndian,
			bool fTextEn
			)
		{
			try
			{
				System.IO.Stream pFileIn = new System.IO.MemoryStream(pBinary, false);
				BinaryReadThru pThruIn = fLittleEndian
					? (BinaryReadThru)new BinaryReadThruLE(pFileIn)
					: (BinaryReadThru)new BinaryReadThruBE(pFileIn);
				int i, n = pBinary[2] * 256 + pBinary[3];
				pListEntries = new Entry[n];
				for (i=0; i<n; i++)
				{
					Entry pEntry = (pListEntries[i] = new Entry());
					int o = 0x14 + 8*i;
					System.Array.Copy(pBinary, o, pEntry.Binary, 0, 8);
				}
				fTextIsEn = fTextEn;
				return true;
			}
			catch(System.Exception err)
			{
				System.Diagnostics.Debug.WriteLine(err.Message);
			}
			return false;
		}
		public Entry QueryEntry(
			int n0,
			int n1,
			int n2,
			int n3,
			int n4,
			int n5
			)
		{
			foreach (Entry p in pListEntries)
			{
				if (true
					&& p.Cat1 == n0
					&& p.Cat2 == n1
					&& p.Cat3 == n2
					&& p.Cat4 == n3
					&& p.Cat5 == n4
					&& p.Cat6 == n5
					)
				{
					return p;
				}
			}
			return null;
		}
		// 
		public Entry[] QueryEntries(
			ETP p0,
			ETP p1,
			ETP p2,
			ETP p3,
			ETP p4,
			ETP p5
			)
		{
			int nEntries = QuerySizeEntries(p0, p1, p2, p3, p4, p5);
			if (nEntries != 0)
			{
				Entry[] pEntries = new Entry[nEntries];
				int i = 0;
				foreach (Entry p in pListEntries)
				{
					if (true
						&& p0.Test((byte)p.Cat1)
						&& p1.Test((byte)p.Cat2)
						&& p2.Test((byte)p.Cat3)
						&& p3.Test((byte)p.Cat4)
						&& p4.Test((byte)p.Cat5)
						&& p5.Test((byte)p.Cat6)
						)
					{
						pEntries[i] = p;

						i++;
					}
				}
				return pEntries;
			}
			return null;
		}
		// 
		public int QuerySizeEntries(
			ETP p0,
			ETP p1,
			ETP p2,
			ETP p3,
			ETP p4,
			ETP p5
			)
		{
			int n = 0;
			foreach (Entry p in pListEntries)
			{
				if (true
					&& p0.Test((byte)p.Cat1)
					&& p1.Test((byte)p.Cat2)
					&& p2.Test((byte)p.Cat3)
					&& p3.Test((byte)p.Cat4)
					&& p4.Test((byte)p.Cat5)
					&& p5.Test((byte)p.Cat6)
					)
				{
					n++;
				}
			}
			return n;
		}
		// 
		public bool ReadAltTextFrom(string PathName)
		{
			try
			{
				WinIni pIni = new WinIni(System.Text.Encoding.UTF8);
				pIni.LoadFrom(PathName);
				System.String[] sNames;
				//
				pTextEN = new System.Collections.SortedList(256);
				sNames = pIni.GetProfileString("DM2AE.en");
				foreach (string lval in sNames)
				{
					string rval = pIni.GetProfileString("DM2AE.en", lval, "");
					int lv = int.Parse(lval, System.Globalization.NumberStyles.HexNumber);
					lv = lv ^ 0xFF;
					pTextEN[lv] = rval;
				}
				//
				pTextJA = new System.Collections.SortedList(512);

				sNames = pIni.GetProfileString("DM2AE.ja.0");
				foreach (string lval in sNames)
				{
					string rval = pIni.GetProfileString("DM2AE.ja.0", lval, "");
					int lv = int.Parse(lval, System.Globalization.NumberStyles.HexNumber) & 0xFF;
					lv = lv ^ 0xFF;
					//System.Diagnostics.Debug.Assert(0 <= lv && lv < 0x100);
					pTextJA[lv] = rval;
				}
				sNames = pIni.GetProfileString("DM2AE.ja.F");
				foreach (string lval in sNames)
				{
					string rval = pIni.GetProfileString("DM2AE.ja.F", lval, "");
					int lv =(int.Parse(lval, System.Globalization.NumberStyles.HexNumber) & 0xFF)|0x100;
					lv = lv ^ 0xFF;
					//System.Diagnostics.Debug.Assert(0x100 <= lv && lv < 0x200);
					pTextJA[lv] = rval;
				}
				//
				return true;
			}
			catch(System.Exception err)
			{
				System.Diagnostics.Debug.WriteLine(err.Message);
			}
			return false;
		}
		// 
		public string DecodeText(
			System.Byte[] Binary
			)
		{
			System.Text.StringBuilder s = new System.Text.StringBuilder(64);
			if (fTextIsEn)
			{
				int i = 0, n = Binary.Length;
				System.Byte iStep = 0;
				while (i < n)
				{
					int c1 = (Binary[i] + iStep) & 0xFF;
					i++; iStep++;
					if (c1 == 0xFF)
						break;
					switch (c1)
					{
						case 0xF5: // 0x0A^0xFF
							s.Append("\n");
							break;
						default:
							string sLookUp = pTextEN[c1] as string;
							if (sLookUp == null)
								sLookUp = "?";
							s.Append(sLookUp);
							break;
					}
				}
			}
			else
			{
				int i = 0, n = Binary.Length;
				System.Byte iStep = 0;
				while (i < n)
				{
					int c1 = (Binary[i] + iStep) & 0xFF;
					i++; iStep++;
					if (c1 == 0xFF)
						break;
					if (c1 == 0x0F)
					{
						c1 = (Binary[i] + iStep) & 0xFF;
						i++; iStep++;
						c1 = c1 | 0x100;
					}
					switch (c1)
					{
						case 0xF5: // 0x0A^0xFF
							s.Append("\n");
							break;
						default:
							string sLookUp = pTextJA[c1] as string;
							if (sLookUp == null)
								sLookUp = "?";
							s.Append(sLookUp);
							break;
					}
				}
			}
			return s.ToString();
		}
	}
}
