namespace Texture_Tool
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Reflection;
    using System.Windows.Forms;
    using Tao.DevIl;

    internal static class Program
    {
        private static readonly string[] SuppFormats = new string[6] { "TMC", "texch", "dlicon", "sprpack", "SCENE", "TNF" };
        private static readonly byte[] ZeroByte = new byte[1] { (byte)0 };
        private static readonly int AlignValue = 16;
        private static AppDomain currentDomain;
        private static DOAHeader mainHeader, ttdmHeader, ttdhHeader, ttdlHeader, iblpkHeader;

        public static bool SwapTexture(List<Texture> texBuffer, int texIndex, string fileName)
        {
            try
            {
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    texBuffer[texIndex] = new Texture(fs, texBuffer[texIndex].RelativeID, (int)fs.Length);
                }

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static bool ExtractTexture(Texture tex, string fileName)
        {
            try
            {
                using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    tex.Buffer.Position = 0;
                    tex.Buffer.CopyTo(fs);
                }

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static Tuple<List<Texture>, int> OpenContainer(int fileType, string fileName)
        {
            try
            {
                var tempTexBuffer = new List<Texture>();
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    mainHeader = new DOAHeader(fs);
                    if (mainHeader.Name != SuppFormats[fileType])
                    {
                        throw new Exception("Unsupported file format!");
                    }

                    mainHeader.Size = (int)fs.Length;
                    int ttdmOffset = 0;
                    switch (fileType)
                    {
                        case 0:
                            ttdmOffset = mainHeader.Table1[1];
                            break;

                        case 1:
                            ttdmOffset = mainHeader.Table1[mainHeader.Table1.Count - 1];
                            break;

                        case 2:
                            ttdmOffset = mainHeader.Table1[mainHeader.Table1.Count - 1];
                            break;

                        case 3:
                            ttdmOffset = mainHeader.Table1[0];
                            break;

                        case 4:
                            fs.Position = mainHeader.Table1[0];
                            iblpkHeader = new DOAHeader(fs);
                            ttdmOffset = iblpkHeader.BaseOffset + iblpkHeader.Table1[1];
                            break;

                        case 5:
                            ttdmOffset = mainHeader.Table1[3];
                            break;
                    }

                    fs.Position = ttdmOffset;
                    ttdmHeader = new DOAHeader(fs);
                    ttdmHeader.Buffer = new byte[ttdmHeader.HeaderSize];
                    fs.Position = ttdmOffset;
                    fs.Read(ttdmHeader.Buffer, 0, ttdmHeader.HeaderSize);
                    if ((fileType == 0) && (ttdmHeader.Count1 > 0))
                    {
                        ReadTextures(fs, ttdmHeader.BaseOffset, ttdmHeader.Table1, ttdmHeader.Table2, "M_", tempTexBuffer);
                    }

                    fs.Position = ttdmHeader.BaseOffset + ttdmHeader.HeaderSize;
                    ttdhHeader = new DOAHeader(fs);
                    ttdhHeader.Buffer = new byte[ttdhHeader.Size];
                    fs.Position = ttdmHeader.BaseOffset + ttdmHeader.HeaderSize;
                    fs.Read(ttdhHeader.Buffer, 0, ttdhHeader.Size);
                    fs.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3;
                    ttdlHeader = new DOAHeader(fs);
                    ttdlHeader.Buffer = new byte[ttdlHeader.Size];
                    fs.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3;
                    fs.Read(ttdlHeader.Buffer, 0, ttdlHeader.Size);
                    if (ttdlHeader.Count1 > 0)
                    {
                        switch (fileType)
                        {
                            case 0:
                                using (var fs2 = new FileStream(Path.ChangeExtension(fileName, ".TMCL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    ReadTextures(fs2, 128, ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                }

                                break;

                            case 1:
                                using (var fs2 = new FileStream(Path.ChangeExtension(fileName, ".--HL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    ReadTextures(fs2, 0, ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                }

                                break;

                            case 2:
                                ReadTextures(fs, mainHeader.Table1[0], ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                break;

                            case 3:
                                using (var fs2 = new FileStream(Path.ChangeExtension(fileName, ".LTF"), FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    ReadTextures(fs2, 0, ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                }

                                break;

                            case 4:
                                using (var fs2 = new FileStream(Path.ChangeExtension(fileName, ".TTGL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    ReadTextures(fs2, 0, ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                }

                                break;

                            case 5:
                                using (var fs2 = new FileStream(Path.ChangeExtension(fileName, ".TNFL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    ReadTextures(fs2, 0, ttdlHeader.Table1, ttdlHeader.Table2, "L_", tempTexBuffer);
                                }

                                break;
                        }
                    }
                }

                var texBuffer = new List<Texture>(tempTexBuffer.Count);
                using (var ms = new MemoryStream(ttdhHeader.Buffer))
                {
                    var br = new BinaryReader(ms);
                    for (int i = 0; i < ttdhHeader.Count1; i++)
                    {
                        string relativeID;
                        br.BaseStream.Position = ttdhHeader.Table1[i];
                        if (br.ReadInt32() == 0)
                        {
                            relativeID = "M_";
                        }
                        else
                        {
                            relativeID = "L_";
                        }

                        relativeID += br.ReadInt32().ToString();
                        foreach (var tex in tempTexBuffer)
                        {
                            if (tex.RelativeID == relativeID)
                            {
                                tex.AbsoluteID = i;
                                texBuffer.Add(tex);
                                break;
                            }
                        }
                    }
                }

                return new Tuple<List<Texture>, int>(texBuffer, ttdmHeader.Count1);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }

        public static bool SaveTMC(List<Texture> texBuffer, string fileName)
        {
            try
            {
                byte[] newTTDM = RebuildTTDM(texBuffer);
                byte[] byteBuffer = new byte[ttdmHeader.BaseOffset];
                byte[] byteBuffer2 = new byte[mainHeader.Size - mainHeader.Table1[2]];
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    fs.Read(byteBuffer, 0, byteBuffer.Length);
                    fs.Position = mainHeader.Table1[2];
                    fs.Read(byteBuffer2, 0, byteBuffer2.Length);
                }

                using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    fs.Write(byteBuffer, 0, byteBuffer.Length);
                    fs.Write(newTTDM, 0, newTTDM.Length);
                    if (ttdmHeader.Count1 > 0)
                    {
                        var sortedTexBuffer = SortTexBuffer(texBuffer, 0);
                        for (int i = 0; i < ttdmHeader.Count1; i++)
                        {
                            ttdmHeader.Table1[i] = (int)fs.Position - ttdmHeader.BaseOffset;
                            ttdmHeader.Table2[i] = (int)sortedTexBuffer[i].Buffer.Length;
                            sortedTexBuffer[i].Buffer.Position = 0;
                            sortedTexBuffer[i].Buffer.CopyTo(fs);
                            AlignStream(fs, AlignValue, false);
                        }

                        ttdmHeader.Size = (int)fs.Position - ttdmHeader.BaseOffset;
                    }

                    int shiftValue = (int)fs.Position - mainHeader.Table1[2];
                    for (int i = 2; i < mainHeader.Table1.Count; i++)
                    {
                        if (mainHeader.Table1[i] == 0)
                        {
                            continue;
                        }

                        mainHeader.Table1[i] += shiftValue;
                    }

                    fs.Write(byteBuffer2, 0, byteBuffer2.Length);
                    mainHeader.Size = (int)fs.Length;
                    var bw = new BinaryWriter(fs);
                    bw.BaseStream.Position = 16;
                    bw.Write(mainHeader.Size);
                    bw.BaseStream.Position = mainHeader.Offset1;
                    foreach (var secOffset in mainHeader.Table1)
                    {
                        bw.Write(secOffset);
                    }

                    if (ttdmHeader.Count1 > 0)
                    {
                        bw.BaseStream.Position = ttdmHeader.BaseOffset + 16;
                        bw.Write(ttdmHeader.Size);
                        bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset1;
                        foreach (var texOffset in ttdmHeader.Table1)
                        {
                            bw.Write(texOffset);
                        }

                        bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset2;
                        foreach (var texSize in ttdmHeader.Table2)
                        {
                            bw.Write(texSize);
                        }
                    }
                }

                if (ttdlHeader.Count1 > 0)
                {
                    byte[] byteBuffer3 = new byte[192];
                    using (var fs = new FileStream(Path.ChangeExtension(fileName, ".TMCL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        fs.Read(byteBuffer3, 0, byteBuffer3.Length);
                    }

                    int tmclSize;
                    using (var fs = new FileStream(Path.ChangeExtension(fileName, ".TMCL"), FileMode.Create, FileAccess.Write, FileShare.Read))
                    {
                        fs.Write(byteBuffer3, 0, byteBuffer3.Length);
                        var sortedTexBuffer = SortTexBuffer(texBuffer, 1);
                        for (int i = 0; i < ttdlHeader.Count1; i++)
                        {
                            ttdlHeader.Table1[i] = (int)fs.Position - 128;
                            ttdlHeader.Table2[i] = (int)sortedTexBuffer[i].Buffer.Length;
                            sortedTexBuffer[i].Buffer.Position = 0;
                            sortedTexBuffer[i].Buffer.CopyTo(fs);
                            AlignStream(fs, AlignValue, false);
                        }

                        AlignStream(fs, AlignValue, true);
                        var bw = new BinaryWriter(fs);
                        tmclSize = (int)fs.Length;
                        bw.BaseStream.Position = 4;
                        bw.Write(tmclSize);
                    }

                    using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Write, FileShare.Read))
                    {
                        var bw = new BinaryWriter(fs);
                        bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3 + ttdlHeader.Offset1;
                        foreach (var texOffset in ttdlHeader.Table1)
                        {
                            bw.Write(texOffset);
                        }

                        bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3 + ttdlHeader.Offset2;
                        foreach (var texSize in ttdlHeader.Table2)
                        {
                            bw.Write(texSize);
                        }

                        bw.BaseStream.Position = mainHeader.Table1[7] + 68;
                        bw.Write(tmclSize);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static void ConvertTMC(List<Texture> texBuffer)
        {
            ttdmHeader.Count1 = 0;
            ttdmHeader.Count2 = 0;
            ttdmHeader.Offset1 = 0;
            ttdmHeader.Offset2 = 0;
            ttdlHeader.Count1 = ttdhHeader.Count1;
            ttdlHeader.Count2 = ttdhHeader.Count2;
            ttdlHeader.Table1 = new List<int>(ttdlHeader.Count1);
            ttdlHeader.Table2 = new List<int>(ttdlHeader.Count2);
            for (int i = 0; i < texBuffer.Count; i++)
            {
                texBuffer[i].RelativeID = "L_" + i.ToString();
                ttdlHeader.Table1.Add(0);
                ttdlHeader.Table2.Add(0);
            }
        }

        public static bool SaveH(List<Texture> texBuffer, string fileName)
        {
            try
            {
                byte[] newTTDM = RebuildTTDM(texBuffer);
                byte[] buffer = new byte[64];
                using (var fs = new FileStream(Path.ChangeExtension(fileName, ".--HL"), FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    fs.Read(buffer, 0, buffer.Length);
                }

                int hlSize;
                using (var fs = new FileStream(Path.ChangeExtension(fileName, ".--HL"), FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    fs.Write(buffer, 0, buffer.Length);
                    for (int i = 0; i < texBuffer.Count; i++)
                    {
                        ttdlHeader.Table1[i] = (int)fs.Position;
                        ttdlHeader.Table2[i] = (int)texBuffer[i].Buffer.Length;
                        texBuffer[i].Buffer.Position = 0;
                        texBuffer[i].Buffer.CopyTo(fs);
                        AlignStream(fs, AlignValue, false);
                    }

                    AlignStream(fs, AlignValue, true);
                    var bw = new BinaryWriter(fs);
                    hlSize = (int)fs.Length;
                    bw.BaseStream.Position = 4;
                    bw.Write(hlSize);
                }

                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Write, FileShare.Read))
                {
                    fs.Position = ttdmHeader.BaseOffset;
                    fs.Write(newTTDM, 0, newTTDM.Length);
                    mainHeader.Size = (int)fs.Length;
                    var bw = new BinaryWriter(fs);
                    bw.BaseStream.Position = 0x10;
                    bw.Write(mainHeader.Size);
                    bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3 + 68;
                    bw.Write(hlSize);
                    bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3 + ttdlHeader.Offset1;
                    foreach (var texOffset in ttdlHeader.Table1)
                    {
                        bw.Write(texOffset);
                    }

                    bw.BaseStream.Position = ttdmHeader.BaseOffset + ttdmHeader.Offset3 + ttdlHeader.Offset2;
                    foreach (var texSize in ttdlHeader.Table2)
                    {
                        bw.Write(texSize);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static bool SaveP(List<Texture> texBuffer, string fileName)
        {
            try
            {
                byte[] buffer = new byte[mainHeader.Table1[0] + 64];
                byte[] buffer2 = new byte[mainHeader.Size - mainHeader.Table1[1]];
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    fs.Read(buffer, 0, buffer.Length);
                    fs.Position = mainHeader.Table1[1];
                    fs.Read(buffer2, 0, buffer2.Length);
                }

                using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    fs.Write(buffer, 0, buffer.Length);
                    ttdlHeader.Table2[0] = (int)texBuffer[0].Buffer.Length;
                    texBuffer[0].Buffer.Position = 0;
                    texBuffer[0].Buffer.CopyTo(fs);
                    AlignStream(fs, AlignValue, false);
                    mainHeader.Table1[1] = (int)fs.Position;
                    ttdmHeader.BaseOffset = mainHeader.Table1[1];
                    ttdlHeader.BaseOffset = ttdmHeader.BaseOffset + ttdmHeader.Offset3;
                    fs.Write(buffer2, 0, buffer2.Length);
                    mainHeader.Size = (int)fs.Length;
                    fs.Position = 16;
                    var bw = new BinaryWriter(fs);
                    bw.Write(mainHeader.Size);
                    bw.BaseStream.Position = mainHeader.Offset1 + 4;
                    bw.Write(mainHeader.Table1[1]);
                    bw.BaseStream.Position = ttdlHeader.BaseOffset + ttdlHeader.Offset2;
                    bw.Write(ttdlHeader.Table2[0]);
                }

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static Bitmap PreviewDDS(byte[] ddsBuffer, int ddsWidth, int ddsHeight)
        {
            int imgName;
            Il.ilGenImages(1, out imgName);
            Il.ilBindImage(imgName);
            Il.ilLoadL(Il.IL_DDS, ddsBuffer, ddsBuffer.Length);
            var r = new Rectangle(0, 0, ddsWidth, ddsHeight);
            Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE);
            var b = new Bitmap(ddsWidth, ddsHeight);
            var bd = b.LockBits(r, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
            Il.ilCopyPixels(0, 0, 0, ddsWidth, ddsHeight, 1, Il.IL_BGRA, Il.IL_UNSIGNED_BYTE, bd.Scan0);
            Il.ilDeleteImages(1, ref imgName);
            b.UnlockBits(bd);
            return b;
        }

        public static Bitmap ResizePreview(Bitmap prvBitmap, int prvWidth, int prvHeight)
        {
            var b = new Bitmap(prvWidth, prvHeight);
            using (Graphics g = Graphics.FromImage((Image)b))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(prvBitmap, 0, 0, prvWidth, prvHeight);
            }

            return b;
        }

        public static Texture AddTexture(string fileName)
        {
            Texture newTex;
            if (fileName != null)
            {
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    newTex = new Texture(fs, "L_" + ttdlHeader.Count1.ToString(), (int)fs.Length);
                }
            }
            else
            {
                using (var ms = new MemoryStream(Texture_Tool.Properties.Resources.texStub))
                {
                    newTex = new Texture(ms, "L_" + ttdlHeader.Count1.ToString(), (int)ms.Length);
                }
            }

            newTex.AbsoluteID = ttdhHeader.Count1;
            if (ttdlHeader.Count1 == 0)
            {
                ttdlHeader.Table1 = new List<int>();
                ttdlHeader.Table2 = new List<int>();
            }

            ttdlHeader.Count1++;
            ttdlHeader.Count2++;
            ttdlHeader.Table1.Add(0);
            ttdlHeader.Table2.Add(0);
            ttdhHeader.Count1++;
            ttdhHeader.Count2++;
            ttdhHeader.Table1.Add(0);
            return newTex;
        }

        private static void ReadTextures(FileStream fs, int baseOffset, List<int> texOffsets, List<int> texSizes, string texIDPrefix, List<Texture> texBuffer)
        {
            for (int i = 0; i < texOffsets.Count; i++)
            {
                fs.Position = baseOffset + texOffsets[i];
                texBuffer.Add(new Texture(fs, texIDPrefix + i, texSizes[i]));
            }
        }

        private static byte[] RebuildTTDM(List<Texture> texBuffer)
        {
            using (var ms = new MemoryStream())
            {
                ms.Write(ttdmHeader.Buffer, 0, ttdmHeader.Buffer.Length);
                ms.Write(ttdhHeader.Buffer, 0, ttdhHeader.Offset1);
                ms.Position += ttdhHeader.Count1 * 4;
                AlignStream(ms, AlignValue, false);
                int ttdhTexTableOffset = (int)ms.Position;
                ms.Position += ttdhHeader.Count1 * 16;
                AlignStream(ms, AlignValue, false);
                ttdhHeader.Size = (int)ms.Position - ttdmHeader.HeaderSize;
                if (ttdmHeader.Count1 > 0)
                {
                    ttdmHeader.Offset1 = (int)ms.Position;
                }

                ms.Position += ttdmHeader.Count1 * 4;
                AlignStream(ms, AlignValue, false);
                if (ttdmHeader.Count1 > 0)
                {
                    ttdmHeader.Offset2 = (int)ms.Position;
                }

                ms.Position += ttdmHeader.Count1 * 4;
                AlignStream(ms, AlignValue, false);
                ttdmHeader.Offset3 = (int)ms.Position;
                ms.Write(ttdlHeader.Buffer, 0, ttdlHeader.HeaderSize);
                if (ttdlHeader.Count1 > 0)
                {
                    ttdlHeader.Offset1 = (int)ms.Position - ttdmHeader.Offset3;
                    ms.Position += ttdlHeader.Count1 * 4;
                    AlignStream(ms, AlignValue, false);
                    ttdlHeader.Offset2 = (int)ms.Position - ttdmHeader.Offset3;
                    ms.Position += ttdlHeader.Count1 * 4;
                    ms.Position -= 1;
                    ms.Write(ZeroByte, 0, 1);
                    AlignStream(ms, AlignValue, false);
                    AlignStream(ms, AlignValue, true);
                }

                ttdmHeader.Size = (int)ms.Length;
                var bw = new BinaryWriter(ms);
                bw.BaseStream.Position = 0x10;
                bw.Write(ttdmHeader.Size);
                bw.Write(ttdmHeader.Count1);
                bw.Write(ttdmHeader.Count2);
                bw.BaseStream.Position += 4;
                if (ttdmHeader.Count1 > 0)
                {
                    bw.Write(ttdmHeader.Offset1);
                    bw.Write(ttdmHeader.Offset2);
                }
                else
                {
                    bw.BaseStream.Position += 8;
                }

                bw.Write(ttdmHeader.Offset3);
                bw.BaseStream.Position = ttdmHeader.HeaderSize + 0x10;
                bw.Write(ttdhHeader.Size);
                bw.Write(ttdhHeader.Count1);
                bw.Write(ttdhHeader.Count2);
                bw.BaseStream.Position = ttdhTexTableOffset;
                for (int i = 0; i < ttdhHeader.Count1; i++)
                {
                    ttdhHeader.Table1[i] = (int)bw.BaseStream.Position - ttdmHeader.HeaderSize;
                    if (texBuffer[i].RelativeID[0] == 'L')
                    {
                        bw.Write(1);
                    }
                    else
                    {
                        bw.Write(0);
                    }

                    bw.Write(int.Parse(texBuffer[i].RelativeID.Substring(2)));
                    bw.BaseStream.Position += 8;
                }

                bw.BaseStream.Position = ttdmHeader.HeaderSize + ttdhHeader.Offset1;
                for (int i = 0; i < ttdhHeader.Count1; i++)
                {
                    bw.Write(ttdhHeader.Table1[i]);
                }

                bw.BaseStream.Position = ttdmHeader.Offset3 + 0x10;
                bw.Write(ttdmHeader.Size - ttdmHeader.Offset3);
                bw.Write(ttdlHeader.Count1);
                bw.Write(ttdlHeader.Count2);
                bw.BaseStream.Position += 4;
                bw.Write(ttdlHeader.Offset1);
                bw.Write(ttdlHeader.Offset2);
                return ms.ToArray();
            }
        }

        private static void AlignStream(Stream s, int alignValue, bool lastAlign)
        {
            if (!lastAlign)
            {
                if (s.Position % alignValue > 0)
                {
                    s.Position = s.Position - (s.Position % AlignValue) + AlignValue;
                }
            }
            else
            {
                if (s.Length % alignValue > 0)
                {
                    s.Position -= 1;
                    s.Write(ZeroByte, 0, 1);
                }
            }
        }

        private static List<Texture> SortTexBuffer(List<Texture> texBuffer, int sortType)
        {
            var sortedTexBuffer = new List<Texture>();
            if (sortType == 0)
            {
                for (int i = 0; i < ttdmHeader.Count1; i++)
                {
                    string relativeID = "M_" + i.ToString();
                    foreach (var tex in texBuffer)
                    {
                        if (tex.RelativeID == relativeID)
                        {
                            sortedTexBuffer.Add(tex);
                            break;
                        }
                    }
                }
            }
            else if (sortType == 1)
            {
                for (int i = 0; i < ttdlHeader.Count1; i++)
                {
                    string relativeID = "L_" + i.ToString();
                    foreach (var tex in texBuffer)
                    {
                        if (tex.RelativeID == relativeID)
                        {
                            sortedTexBuffer.Add(tex);
                            break;
                        }
                    }
                }
            }

            return sortedTexBuffer;
        }

        private static Assembly ResolveEventHandler(Object sender, ResolveEventArgs args)
        {
            string dllName = new AssemblyName(args.Name).Name + ".dll";
            if (dllName != "Tao.DevIl.dll")
            {
                return null;
            }
            else
            {
                currentDomain.AssemblyResolve -= ResolveEventHandler;
                return Assembly.Load(Texture_Tool.Properties.Resources.Tao_DevIl);
            }
        }

        [STAThread]
        private static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            currentDomain = AppDomain.CurrentDomain;
            currentDomain.AssemblyResolve += ResolveEventHandler;
            Application.Run(new MainForm());
        }
    }
}