using RecrownedAthenaeum.Tools.CommandProcessor;
using RecrownedAthenaeum.Tools.TextureAtlas;
using System;
using System.IO;

namespace RecrownedAthenaeum.Tools.TextureAtlasTools
{
    class TexturePackerCommand : EngineCommand
    {
        private const int DMP = 9;
        private const int DSP = 6;
        public TexturePackerCommand() : base("texturepacker")
        {
            help = "Packs a given directory composed of png and jpg files into an atlas. Can also add 9patch properties. Images with the associated \".9p\" files will automatically be defined in the resulting .tatlas file, but can be overwritten by use of the \"-9p\" argument.";
            commandArguments = new[] {
                new EngineCommandArgument("-interactive", "runs in interactive mode. Ninepatches must still be defined with arguments or previously defined with associated \".9p\" files. Other arguments will be ignored."),
                new EngineCommandArgument("-i", "for input directory containing the textures.", true),
                new EngineCommandArgument("-o", "Path for output files. Points to non-existent file. Will create texture and definitions file with name.", true),
                new EngineCommandArgument("-9p", "Can be used multiple times for defining a 9patch. This parameter requires a name, left patch, right patch, top patch, and bottom patch in the format \"name,a,b,c,d\"."),
                new EngineCommandArgument("-sp", "Starting power for one side of the texture. Default is " + DSP + "."),
                new EngineCommandArgument("-mp", "Maximum power for one side of the texture. Default is " + DMP + "."),
                new EngineCommandArgument("-dau", "Disables automatically upscaling the texture."),
            };
        }

        public override void Run(string[] arguments)
        {

            TexturePacker texturePacker = null;
            string path = null;
            int mp = DMP;
            int sp = DSP;
            bool dau = false;
            string output = null;

            if (HasArgument("-interactive", arguments))
            {
                string input;
                ConsoleUtilities.WriteWrappedLine("Texture packer interactive mode triggered. Type \"q\" at any time to exit.");
                ConsoleUtilities.WriteWrappedLine("Please enter path of folder containing the textures to be packed.");
                input = Console.ReadLine();
                if (input == "q") return;
                path = input.Replace("\"", "");

                ConsoleUtilities.WriteWrappedLine("Please enter output path of file name.");
                input = Console.ReadLine();
                if (input == "q") return;
                output = input.Replace("\"", "");

                do
                {
                    ConsoleUtilities.WriteWrappedLine("Please enter a valid starting power of two for the lengths of the resulting texture atlas. Leave blank for default of " + sp + ".");
                    input = Console.ReadLine();
                    if (input == "q") return;
                    if (input.Length == 0) break;
                } while (!int.TryParse(input, out sp));

                do
                {
                    ConsoleUtilities.WriteWrappedLine("Please enter a valid maximum power by two of the lengths of the resulting texture atlas. Leave blank for default of " + mp + ".");
                    input = Console.ReadLine();
                    if (input == "q") return;
                    if (input.Length == 0) break;
                } while (!int.TryParse(input, out mp));

            }
            else
            {
                int indexOfInputArg = IndexOfArgument("-i", arguments);
                if (indexOfInputArg + 1 >= arguments.Length) throw new ArgumentException("-i is not followed by input path.");
                path = arguments[1 + IndexOfArgument("-i", arguments)];
                if (HasArgument("-mp", arguments))
                {
                    int.TryParse(arguments[IndexOfArgument("-mp", arguments) + 1], out mp);
                }
                if (HasArgument("-sp", arguments))
                {
                    int.TryParse(arguments[IndexOfArgument("-sp", arguments) + 1], out sp);
                }
                int indexOfOutputArg = IndexOfArgument("-o", arguments);
                if (indexOfOutputArg + 1 >= arguments.Length) throw new ArgumentException("-o is not followed by input path.");
                output = arguments[IndexOfArgument("-o", arguments) + 1];
                if (HasArgument("-dau", arguments)) dau = true;
            }

            texturePacker = new TexturePacker(path, mp, sp);
            ConsoleUtilities.WriteWrappedLine("Calculated minimum texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + " with a total of " + texturePacker.TexturesFound + " textures.");

            try
            {
                texturePacker.Build(!dau);
            }
            catch (InvalidOperationException e)
            {
                throw new ArgumentException(e.Message);
            }

            for (int i = 0; i < arguments.Length; i++)
            {
                if (arguments[i] == "-9p")
                {
                    if (i + 1 >= arguments.Length) throw new ArgumentException("-9p is not followed by proper specifiers for a 9Patch (format: \"-9p textureName,a,b,c,d\" where a, b, c, and d are integers definining the border regions for the 9patch.)");
                    string[] nPatchArgs = arguments[i + 1].Split(',');
                    try
                    {
                        texturePacker.SetNinePatch(nPatchArgs[0], int.Parse(nPatchArgs[1]), int.Parse(nPatchArgs[2]), int.Parse(nPatchArgs[3]), int.Parse(nPatchArgs[4]));
                    }
                    catch (FormatException)
                    {
                        throw new ArgumentException("-9p argument parameters must be in the format \"-9p textureName,a,b,c,d\" where a, b, c, and d are integers definining the border regions for the 9patch.");
                    }
                }
            }
            texturePacker.Save(Path.GetDirectoryName(output), Path.GetFileName(output));
            Console.WriteLine("Complete. Final texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + ".");
        }
    }
}
