using System;

namespace DM2CompressPic
{
	// 
	public class DM2AEShared
	{
		// 
		public static string g_sIni = "DM2AE.ini";
		// 
		public static string IniPath
		{
			get { return GetNeighborFile(g_sIni); }
		}

		// 
		public DM2AEShared()
		{

		}
		// 
		public static System.String GetDir(
			System.String X
			)
		{
			int i = X.LastIndexOf('\\');
			if (i != -1)
				return X.Substring(0, i + 1);
			return "";
		}
		// 
		public static System.String GetFileName(
			System.String X
			)
		{
			int i = X.LastIndexOf('\\');
			if (i != 1)
				return X.Substring(i + 1);
			return X;
		}
		// 
		public static System.String JoinPath(
			System.String Dir, System.String File
			)
		{
			if (Dir.LastIndexOf('\\') != Dir.Length - 1)
				Dir += '\\';
			return Dir + File;
		}
		// 
		public static System.String GetNeighborFile(
			System.String File
			)
		{
			return JoinPath(System.AppDomain.CurrentDomain.BaseDirectory, File);
		}
		// 
		public static System.String EncodeToHtmlText(
			System.String Html
			)
		{
			System.Text.StringBuilder s = new System.Text.StringBuilder(Html, Html.Length * 2);
			s.Replace("&", "&amp;");
			s.Replace("<", "&lt;");
			s.Replace(">", "&gt;");
			return s.ToString();
		}
		// 
		public static System.String Bin2Str(
			System.Byte[] X
			)
		{
			System.Text.StringBuilder s = new System.Text.StringBuilder(X.Length * 3 + 16);
			int i = 0;
			foreach (System.Byte x in X)
			{
				if (i != 0)
				{
					s.Append(' ');
				}
				if (x < 16)
				{
					s.Append('0');
					s.Append(x.ToString("X"));
				}
				else
				{
					s.Append(x.ToString("X"));
				}
				i++;
			}
			return s.ToString();
		}
		// 
		public static System.Byte[] Str2Bin(
			System.String s
			)
		{
			int i = 0, n = s.Length;
			int m = 0;
			for (; i < n; i++)
			{
				char c = s[i];
				if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
				{
					m++;
				}
			}
			if (m == 0)
			{
				return null;
			}
			System.Byte[] X = new System.Byte[(m + 1) / 2];
			int t = 0, x = 0;
			int o = 0;
			bool Lead = true;
			i = 0;
			for (; i < n; i++)
			{
				char c = s[i];
				switch (c)
				{
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
					case 'a':
					case 'b':
					case 'c':
					case 'd':
					case 'e':
					case 'f':
					case 'A':
					case 'B':
					case 'C':
					case 'D':
					case 'E':
					case 'F':
					switch (c)
					{
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							t = c - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							t = c - 'a' + 10;
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							t = c - 'A' + 10;
							break;
					}
						if (Lead)
						{
							x = (t&0x0F)<<4;
						}
						else
						{
							x|= (t&0x0F);
							X[o] = (System.Byte)x;
							o++;
							x = 0;
						}
						Lead = !Lead;
						break;
				}
			}
			return X;
		}
	}

	// 
	public class WinIni
	{
		// 
		class Pair
		{
			// 
			private System.String m_pKey;
			// 
			private System.String m_pVal;
			// 
			public Pair(
				System.String pKey,
				System.String pVal
				)
			{
				m_pKey = pKey;
				m_pVal = pVal;
			}
			// 
			public System.String Key
			{
				get { return m_pKey; }
			}
			// 
			public System.String Value
			{
				get { return m_pVal; }
			}
		};
		// 
		class Section
		{
			// 
			private System.String m_pKey;
			// 
			private System.Collections.SortedList m_pPairs;
			// 
			public Section(
				System.String pKey
				)
			{
				m_pKey = pKey;
				m_pPairs = new System.Collections.SortedList();
			}
			// 
			public System.String Key
			{
				get { return m_pKey; }
			}
			// 
			public System.Collections.SortedList Pairs
			{
				get { return m_pPairs; }
			}
		};

		// 
		private System.Collections.SortedList m_pSections;
		// 
		private System.Text.Encoding m_pEncoding;

		// 
		public WinIni()
		{
			m_pSections = new System.Collections.SortedList();
			m_pEncoding = System.Text.Encoding.Default;
		}
		// 
		public WinIni(
			System.Text.Encoding pEncoding
			)
		{
			m_pSections = new System.Collections.SortedList();
			m_pEncoding = pEncoding;
		}
		// 
		public System.String GetProfileString(
			System.String sApp,
			System.String sKey,
			System.String sDef
			)
		{
			Section pSection = (Section)m_pSections[sApp.ToLower()];
			if (pSection != null)
			{
				Pair pPair = (Pair)pSection.Pairs[sKey.ToLower()];
				if (pPair != null)
				{
					return pPair.Value;
				}
			}
			return sDef;
		}
		// 
		public System.String[] GetProfileString(
			System.String sApp
			)
		{
			Section pSection = (Section)m_pSections[sApp.ToLower()];
			if (pSection != null)
			{
				int i = 0, n = pSection.Pairs.Count;
				System.String[] pNames = new System.String[n];
				foreach (Pair pPair in pSection.Pairs.Values)
				{
					pNames[i] = pPair.Key;
					i++;
				}
				return pNames;
			}
			return null;
		}
		// 
		public void WriteProfileString(
			System.String sApp,
			System.String sKey,
			System.String sVal
			)
		{
			Section pSection = (Section)m_pSections[sApp.ToLower()];
			if (pSection == null)
			{
				m_pSections[sApp.ToLower()] = (pSection = new Section(sApp));
			}
			Pair pPair = new Pair(sKey, sVal);
			pSection.Pairs[sKey.ToLower()] = pPair;
		}
		// 
		public bool LoadFrom(System.String FileName)
		{
			try
			{
				m_pSections.Clear();

				System.IO.StreamReader ReadIn = new System.IO.StreamReader(FileName, m_pEncoding);
				System.String sLine = null;

				while (true)
				{
					if (sLine == null)
						sLine = ReadIn.ReadLine();
					if (sLine == null)
						break;
					if (IsCommentLine(sLine))
					{
						sLine = null;
						continue;
					}
					if (IsSectionBracketExist(sLine))
					{
						System.String sApp = sLine.Substring(1, sLine.Length - 2);
						while (true)
						{
							sLine = ReadIn.ReadLine();
							if (sLine == null)
								break;
							if (IsCommentLine(sLine))
							{
								sLine = null;
								continue;
							}
							if (IsSectionBracketExist(sLine))
								break;
							int i = sLine.IndexOf('=');
							if (i < 0)
								continue;
							System.String sKey = sLine.Substring(0, i);
							System.String sVal = sLine.Substring(i + 1);
							WriteProfileString(sApp, sKey, sVal);
						}
					}
				}

				ReadIn.Close();
				return true;
			}
			catch(System.Exception err)
			{
				System.Diagnostics.Debug.WriteLine(err.Message);

				m_pSections.Clear();
				return false;
			}
		}
		// 
		public bool SaveTo(System.String FileName)
		{
			try
			{
				System.IO.StreamWriter WriteInto = new System.IO.StreamWriter(FileName, false, m_pEncoding);

				System.Text.StringBuilder s = new System.Text.StringBuilder(256);

				foreach (Section pSection in m_pSections.Values)
				{
					s.Length = 0;
					s.Append('[');
					s.Append(pSection.Key);
					s.Append(']');
					WriteInto.WriteLine(s.ToString());

					foreach (Pair pPair in pSection.Pairs.Values)
					{
						s.Length = 0;
						s.Append(pPair.Key);
						s.Append('=');
						s.Append(pPair.Value);
						WriteInto.WriteLine(s.ToString());
					}
				}

				WriteInto.Close();
				return true;
			}
			catch(System.Exception err)
			{
				System.Diagnostics.Debug.WriteLine(err.Message);
				return false;
			}
		}

		// 
		static private bool IsCommentLine(System.String s)
		{
			s = s.Trim();
			if (s.Length < 2 || s[0] == ';')
				return true;
			return false;
		}
		// 
		static private bool IsSectionBracketExist(System.String s)
		{
			if (s.Length < 3)
				return false;
			if (s[0] == '[' && s[s.Length - 1] == ']')
				return true;
			return false;
		}
	}

	// 
	public abstract class BinaryReadThru
	{
		// 
		private System.IO.Stream m_FileIn;
		// 
		public BinaryReadThru(
			System.IO.Stream FileIn)
		{
			m_FileIn = FileIn;
		}
		// 
		public System.Byte ReadByte()
		{
			int x = m_FileIn.ReadByte();
			if (x == -1)
				throw new System.IO.EndOfStreamException("EOF Reached.");
			return (System.Byte)x;
		}
		// 
		public System.Byte[] ReadBytes(int n)
		{
			System.Byte[] x = new System.Byte[n];
			if (m_FileIn.Read(x, 0, n) != n)
				throw new System.IO.EndOfStreamException("EOF Reached.");
			return x;
		}
		// 
		public abstract System.UInt16 ReadWord();
		// 
		public abstract System.UInt32 ReadDWord();
	};
	// 
	public class BinaryReadThruLE : BinaryReadThru
	{
		// 
		public BinaryReadThruLE(
			System.IO.Stream FileIn) : base(FileIn)
		{

		}
		// 
		public override System.UInt16 ReadWord()
		{
			return (System.UInt16)(0
				|(ReadByte() << 0)
				|(ReadByte() << 8)
				);
		}
		// 
		public override System.UInt32 ReadDWord()
		{
			return (System.UInt32)(0
				|(ReadWord() << 0)
				|(ReadWord() <<16)
				);
		}
	};
	// 
	public class BinaryReadThruBE : BinaryReadThru
	{
		// 
		public BinaryReadThruBE(
			System.IO.Stream FileIn) : base(FileIn)
		{

		}
		// 
		public override System.UInt16 ReadWord()
		{
			return (System.UInt16)(0
				|(ReadByte() << 8)
				|(ReadByte() << 0)
				);
		}
		// 
		public override System.UInt32 ReadDWord()
		{
			return (System.UInt32)(0
				|(ReadWord() <<16)
				|(ReadWord() << 0)
				);
		}
	};
	// 
	public class BinaryThruRead4Bit
	{
		// 
		private System.IO.Stream m_FileIn;
		// 
		private System.Byte m_Data, m_DataMask;
		// 
		private System.Byte ReadByte()
		{
			int x = m_FileIn.ReadByte();
			if (x == -1)
				throw new System.IO.EndOfStreamException("EOF Reached.");
			return (System.Byte)x;
		}
		// 
		public BinaryThruRead4Bit(
			System.IO.Stream FileIn)
		{
			m_FileIn = FileIn;
			m_Data = m_DataMask = 0;
		}
		// 
		public void Close()
		{
			m_FileIn = null;
			m_Data = m_DataMask = 0;
		}
		// 
		public System.Byte Read4Bit()
		{
			if (m_DataMask == 0)
			{
				m_Data = ReadByte();
				m_DataMask = 0xFF;
			}
			System.Byte RetVal = (System.Byte)((m_Data & 0xf0) / 16);
			m_DataMask = (System.Byte)((m_DataMask * 16) & 0xf0);
			m_Data = (System.Byte)((m_Data * 16) & 0xf0);
			//System.Diagnostics.Debug.WriteLine("B:" + RetVal.ToString("X"));
			return RetVal;
		}
		// 
		public System.Byte Peek4Bit()
		{
			if (m_DataMask == 0)
			{
				m_Data = ReadByte();
				m_DataMask = 0xFF;
			}
			return (System.Byte)((m_Data & 0xf0) / 16);
		}
	};
	// 
	public class CombineStoreA2B
	{
		// 
		private System.Collections.Hashtable m_A2B;

		// 
		public CombineStoreA2B()
		{
			m_A2B = new System.Collections.Hashtable(1);
		}
		// 
		public CombineStoreA2B(
			System.Byte[] Binary,
			bool fLittleEndian
			)
		{
			System.IO.Stream Mem = new System.IO.MemoryStream(Binary, false);
			BinaryReadThru ReadIn =
				fLittleEndian
				? (BinaryReadThru)new BinaryReadThruLE(Mem)
				: (BinaryReadThru)new BinaryReadThruBE(Mem);

			m_A2B = new System.Collections.Hashtable(Binary.Length / 2);

			for (int i = 0, n = Binary.Length / 4; i < n; i++)
			{
				int v1 = (int)ReadIn.ReadWord();
				int v2 = (int)ReadIn.ReadWord();
				m_A2B[v1] = v2;
			}
		}
		// 
		public int[] Track(
			int i
			)
		{
			System.Text.StringBuilder s = new System.Text.StringBuilder(32);
			s.Append(i);
			object pNext = m_A2B[i];
			while (pNext != null)
			{
				i = (int)pNext;

				s.Insert(0, "/");
				s.Insert(0, i);

				pNext = m_A2B[i];
			}
			System.String[] sIdxes = s.ToString().Split('/');
			int[] iIdxes = new int[sIdxes.Length];
			int x = 0;
			foreach (System.String str in sIdxes)
			{
				iIdxes[x] = int.Parse(str);
				x++;
			}
			return iIdxes;
		}
		// 
		public bool IsInitialized()
		{
			return (m_A2B.Count > 0) ? true : false;
		}
	}
	// 
	public class PalDM2Combine
	{
		// 
		System.Byte[,] m_CombineInfo;
		// 
		public PalDM2Combine(BinaryThruRead4Bit ReadIn)
		{
			m_CombineInfo = new System.Byte[16, 2];
			for (int i=0; i<16; i++)
			{
				m_CombineInfo[i, 0] = ReadIn.Read4Bit();
				m_CombineInfo[i, 1] = ReadIn.Read4Bit();
			}
		}
		// 
		public void Combine(
			System.Drawing.Color[] Palettes,
			System.Drawing.Color[] AltPalettes)
		{
			for (int i=0; i<16; i++)
			{
				System.Byte x = m_CombineInfo[i, 0];
				System.Byte y = m_CombineInfo[i, 1];
				Palettes[i] = System.Drawing.Color.FromArgb(
					AltPalettes[x].R * y / 15,
					AltPalettes[x].G * y / 15,
					AltPalettes[x].B * y / 15);
			}
		}
	};
	// 
	public class Pal2ColorIdxer
	{
		// 
		private System.Byte[] m_Order;
		// 
		private static void Swap(
			ref System.Byte s1,
			ref System.Byte s2)
		{
			System.Byte
				n1 = s2,
				n2 = s1;
			s1 = n1;
			s2 = n2;
		}
		// 
		public Pal2ColorIdxer(
			System.UInt32 n24Bit,
			int nBits)
		{
			int i, j;
			m_Order = new System.Byte[16];
			for (i = 0; i < 16; i++) m_Order[i] = (System.Byte)i;
			nBits = System.Math.Min(6, System.Math.Max(5, nBits));
			for (i = 0; i < nBits; i++)
			{
				n24Bit <<= 4;
				System.Byte x = (System.Byte)((n24Bit >> 24) & 0x0000000f);
				for (j = 0; j < 16 && m_Order[j] != x; j++);
				int p1 = 8 + i;
				int p2 = j;
				Swap(ref m_Order[p1], ref m_Order[p2]);
			}
		}
		// 
		public void ApplyOrder(
			System.Drawing.Color[] c1,
			System.Drawing.Color[] c2)
		{
			for (int i = 0; i < 16; i++)
			{
				c2[i] = c1[m_Order[i]];
			}
		}
		// 
		public void GetMostUsed6Colors(
			System.Byte[] p1
			)
		{
			for (int i = 0; i < 6; i++) p1[i] = (System.Byte)m_Order[8 + i];
		}
	}
}
