using CXMLDecompiler;
using General;
using Ionic.Zlib;
using System;
using System.IO;
using System.Reflection;

namespace CXMLCli
{
    class Program
    {
        static bool HasArg(string argsfull, string argcheck)
        {
            string[] args = argsfull.Split(' ');
            foreach(string arg in args)
            {
                if(arg == argcheck)
                {
                    return true;
                }
            }

            return false;
        }
        static int Main(string[] args)
        {
	    
            // Do you have gimconv?
            
            bool windowsNT = Environment.OSVersion.Platform.Equals(PlatformID.Win32NT);
            bool windows32 = Environment.OSVersion.Platform.Equals(PlatformID.Win32Windows);
            bool windows32S = Environment.OSVersion.Platform.Equals(PlatformID.Win32S);
            bool windowsCE = Environment.OSVersion.Platform.Equals(PlatformID.WinCE);
            
            if (windowsNT || windows32 || windows32S || windowsCE)
            {
		    if (!File.Exists(Path.Combine("GimConv", "GimConv.exe"))) 
		    {
		        GimConv.DownloadGimConv(); // Politely ask sony to give it to us.
		    }
	    }
	    else
	    {
	    	Console.WriteLine("NOTE: GimConv is windows binary, so you cant use it on this OS!\n.GIM Decoding will be disabled!");
	    }

            bool Check = true;

            if (args.Length == 0)
            {
                Console.WriteLine("-- app.info/CXML Decompiler --");
                Console.WriteLine("I like to see girls die :3");
                Console.WriteLine("Required Arguments:");
                Console.WriteLine("\t<input_filename>");
                Console.WriteLine("Optional Arguments:");
                Console.WriteLine("\t-iv --is-vag               File is HE-VAG audio and NOT CXML");
                Console.WriteLine("\t-dc --decompress           Decompress .Z File");
                Console.WriteLine("\t-cc --compress             Compress back to .Z File");
                Console.WriteLine("\t-f --force                 Dont check magic number.");
                Console.WriteLine("\t-dt --dump-tables          Dump ALL tables.");
                Console.WriteLine("\t-tt --dump-tree            Dump tree table.");
                Console.WriteLine("\t-ist --dump-string-id      Dump string ID table.");
                Console.WriteLine("\t-iit --dump-int-id         Dump int ID table.");
                Console.WriteLine("\t-st --dump-string          Dump string table.");
                Console.WriteLine("\t-ct --dump-char            Dump char table.");
                Console.WriteLine("\t-hit --dump-hash-id        Dump hash ID table.");
                Console.WriteLine("\t-iat --dump-int-array      Dump int array table.");
                Console.WriteLine("\t-fat --dump-float-array    Dump float array table.");
                Console.WriteLine("\t-ft --dump-file            Dump file table.");
                Console.WriteLine("\t-p --process-files         Process Extracted Files");
                Console.WriteLine("\t-nr --no-recursive         Do not recursively decompile .RCS to XML");
                Console.WriteLine("\t-w --wait-exit             Wait for keypress before exiting");
                Console.WriteLine("\t-d --decompile             Decompile CXML to XML.");
                Console.WriteLine("\t-c --compile               Compile XML to CXML");
                Console.WriteLine("\t-h --hash-string           When Compiling, Generate new hashes");
                Console.WriteLine("Example Decompile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " app.info -d -p");
                Console.WriteLine("Example Compile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " app.xml app.info -c");
                Console.WriteLine("Default functonality is to Decompile,\nThis is canceled if any other arguments passed.");
                return 0;
            }

            String ArgsFull = String.Join(" ", args);
            String path = args[0];

            if (args.Length == 1)
            {
                ArgsFull += " -d -p -w";
            }

            if (HasArg(ArgsFull, "-iv") || HasArg(ArgsFull, "--is-vag"))
            {
                byte[] WaveData = VAG.VAGAudio.Vag2Wav(path);
                string FileName = Path.GetFileNameWithoutExtension(path) + "-" + VAG.VAGAudio.GetFilename(path) + ".wav";
                Console.WriteLine("Writing "+FileName);
                File.WriteAllBytes(FileName, WaveData);
                return 0;
            }

            if (HasArg(ArgsFull, "-dc") || HasArg(ArgsFull, "--decompress"))
            {
                Console.WriteLine("Decompressing " + path);
                Byte[] FileData = File.ReadAllBytes(path);
                Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData);
                string Extension = Tools.GetFileExtension(DecompressedData);
                string OutPath = Path.ChangeExtension(path, Extension);
                File.WriteAllBytes(OutPath, DecompressedData);
                return 0;
            }

            if (HasArg(ArgsFull, "-cc") || HasArg(ArgsFull, "--compress"))
            {
                Console.WriteLine("Compressing " + path);
                Byte[] FileData = File.ReadAllBytes(path);
                Byte[] CompressedData = ZlibStream.CompressBuffer(FileData);
                string Extension = Tools.GetFileExtension(CompressedData);
                string OutPath = Path.ChangeExtension(path, Extension);
                File.WriteAllBytes(OutPath, CompressedData);
                return 0;
            }

            CXML.CXMLParser cxmlParser = new CXML.CXMLParser();
            if(!HasArg(ArgsFull, "-c") && !HasArg(ArgsFull, "--compile"))
            {
                Console.WriteLine("Initalizing: " + path);
                cxmlParser.Init(path, Check);
            }


            if (HasArg(ArgsFull, "-f") || HasArg(ArgsFull, "--force"))
            {
                Check = false;
            }

            if (HasArg(ArgsFull, "-dt") || HasArg(ArgsFull, "--dump-tables"))
            {
                ArgsFull += " -tt -ist -iit -st -ct -sit -iat -fat -ft";
            }

            if (HasArg(ArgsFull, "-tt") || HasArg(ArgsFull, "--dump-tree"))
            {
                Console.WriteLine("Dumping tree table.");
                File.WriteAllBytes("tree-table.bin", cxmlParser.GetTreeTable());

            }

            if (HasArg(ArgsFull, "-ist") || HasArg(ArgsFull, "--dump-string-id"))
            {
                Console.WriteLine("Dumping string ID table.");
                File.WriteAllBytes("string-id-table.bin", cxmlParser.GetStringIDTable());

            }

            if (HasArg(ArgsFull, "-iit") || HasArg(ArgsFull, "--dump-int-id"))
            {
                Console.WriteLine("Dumping int ID table.");
                File.WriteAllBytes("int-id-table.bin", cxmlParser.GetIntIDTable());
            }

            if (HasArg(ArgsFull, "-st") || HasArg(ArgsFull, "--dump-string"))
            {
                Console.WriteLine("Dumping string table.");
                File.WriteAllBytes("string-table.bin",cxmlParser.GetStringTable());

            }

            if (HasArg(ArgsFull, "-ct") || HasArg(ArgsFull, "--dump-char"))
            {
                Console.WriteLine("Dumping char table.");
                File.WriteAllBytes("char-table.bin", cxmlParser.GetCharTable());
            }

            if ((HasArg(ArgsFull, "-sit") || HasArg(ArgsFull, "--dump-style-id")) /*kept for backwards comp*/ || (HasArg(ArgsFull, "-hit") || HasArg(ArgsFull, "--dump-hash-id")))
            {
                Console.WriteLine("Dumping hash ID table.");
                File.WriteAllBytes("hash-id-table.bin", cxmlParser.GetHashIDTable());
            }


            if (HasArg(ArgsFull, "-iat") || HasArg(ArgsFull, "--dump-int-array"))
            {
                Console.WriteLine("Dumping int array table.");
                File.WriteAllBytes("int-array-table.bin", cxmlParser.GetIntArrayTable());
            }

            if (HasArg(ArgsFull, "-fat") || HasArg(ArgsFull, "--dump-float-array"))
            {
                Console.WriteLine("Dumping float array table.");
                File.WriteAllBytes("float-array-table.bin", cxmlParser.GetFloatArrayTable());
            }


            if (HasArg(ArgsFull, "-ft") || HasArg(ArgsFull, "--dump-tree"))
            {
                Console.WriteLine("Dumping file table.");
                File.WriteAllBytes("file-table.bin", cxmlParser.GetFileTable());
            }

            if (HasArg(ArgsFull, "-p") || HasArg(ArgsFull, "--process-files"))
            {
                cxmlParser.ProcessFiles = true;
            }

            if (HasArg(ArgsFull, "-w") || HasArg(ArgsFull, "--wait-exit"))
            {
                cxmlParser.WaitExit = true;
            }

            if (HasArg(ArgsFull, "-nr") || HasArg(ArgsFull, "--no-recursive"))
            {
                cxmlParser.NoRecursive = true;
            }

            if (HasArg(ArgsFull, "-d") || HasArg(ArgsFull, "--decompile") && !HasArg(ArgsFull, "-dt"))
            {
                Console.WriteLine("Decompiling.");
                cxmlParser.DecompileCXML(path, Check);
                Console.WriteLine("\n\nDECOMPILATION COMPLETE!");
                if(cxmlParser.WaitExit)
                    Console.ReadKey();
            }
            else if (HasArg(ArgsFull, "-c") || HasArg(ArgsFull, "--compile"))
            {
                Console.WriteLine("Compiling: " + path);
                CXMLBuilder builder = new CXMLBuilder();
                if (HasArg(ArgsFull, "-h") || HasArg(ArgsFull, "----hash-string"))
                    builder.HashStrings = true;

                builder.Init(path, args[1]);
                builder.BuildCXML(path, args[1]);
                Console.WriteLine("\n\nCOMPILATION COMPLETE!");
                if (cxmlParser.WaitExit)
                    Console.ReadKey();
            }

            return 0;
        }
    }
}
