using Godot;
using Theriapolis.GodotHost.Platform;
using Theriapolis.GodotHost.Rendering;
using Theriapolis.GodotHost.UI;

namespace Theriapolis.GodotHost;

// Control (not Node) so child Control scenes (Wizard, KitchenSink, etc.)
// can anchor to a real rect that fills the viewport. With a plain Node
// parent, anchors are ignored and Controls sit at (0,0) at intrinsic min
// size, which causes wide content to overflow off the right edge.
public partial class Main : Control
{
    public override void _Ready()
    {
        // GetCmdlineArgs returns every arg (Godot's own flags + ours);
        // GetCmdlineUserArgs only returns args after a "--" separator.
        // Use the union so users don't have to remember the separator.
        var userArgs = OS.GetCmdlineUserArgs();
        var allArgs = OS.GetCmdlineArgs();
        var args = new string[userArgs.Length + allArgs.Length];
        userArgs.CopyTo(args, 0);
        allArgs.CopyTo(args, userArgs.Length);

        ulong? smokeTestSeed = null;
        ulong? worldMapSeed = null;
        bool runAssetTest = false;
        bool runCodexTest = false;
        bool runWizard = false;
        (ulong seed, int tx, int ty)? tacticalArgs = null;
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] == "--codex-test")
            {
                runCodexTest = true;
                break;
            }
            if (args[i] == "--wizard")
            {
                runWizard = true;
                break;
            }
            if (args[i] == "--smoke-test")
            {
                ulong seed = 12345UL;
                if (i + 1 < args.Length && ulong.TryParse(args[i + 1], out var parsed))
                    seed = parsed;
                smokeTestSeed = seed;
                break;
            }
            if (args[i] == "--asset-test")
            {
                runAssetTest = true;
                break;
            }
            if (args[i] == "--world-map")
            {
                ulong seed = 12345UL;
                if (i + 1 < args.Length && ulong.TryParse(args[i + 1], out var parsed))
                    seed = parsed;
                worldMapSeed = seed;
                break;
            }
            if (args[i] == "--tactical")
            {
                ulong seed = 12345UL;
                int tx = 128, ty = 128;
                if (i + 1 < args.Length && ulong.TryParse(args[i + 1], out var s))
                    seed = s;
                if (i + 2 < args.Length && int.TryParse(args[i + 2], out var x))
                    tx = x;
                if (i + 3 < args.Length && int.TryParse(args[i + 3], out var y))
                    ty = y;
                tacticalArgs = (seed, tx, ty);
                break;
            }
        }

        if (smokeTestSeed.HasValue)
        {
            int code = SmokeTest.Run(smokeTestSeed.Value);
            GetTree().Quit(code);
            return;
        }

        if (runAssetTest)
        {
            int code = AssetTest.Run();
            GetTree().Quit(code);
            return;
        }

        if (worldMapSeed.HasValue)
        {
            // M4: unified seamless-zoom view. --world-map starts zoomed out
            // (fit-to-viewport, initialZoom=0 = compute fit), --tactical
            // starts at native sprite zoom 32 with the player at the given
            // tile. Wheel between them seamlessly.
            foreach (Node child in GetChildren())
                child.QueueFree();
            AddChild(new WorldView(worldMapSeed.Value));
            return;
        }

        if (tacticalArgs.HasValue)
        {
            foreach (Node child in GetChildren())
                child.QueueFree();
            var (seed, tx, ty) = tacticalArgs.Value;
            AddChild(new WorldView(seed, tx, ty, initialZoom: 32f));
            return;
        }

        if (runCodexTest)
        {
            foreach (Node child in GetChildren())
                child.QueueFree();
            AddChild(new KitchenSink());
            return;
        }

        if (runWizard)
        {
            foreach (Node child in GetChildren())
                child.QueueFree();
            var packed = ResourceLoader.Load<PackedScene>("res://Scenes/Wizard.tscn");
            AddChild(packed.Instantiate());
            return;
        }

        GD.Print("Theriapolis.Godot host ready (M0 hello-world).");
    }

    public override void _UnhandledInput(InputEvent @event)
    {
        if (@event.IsActionPressed("ui_toggle_fullscreen"))
        {
            var mode = DisplayServer.WindowGetMode();
            DisplayServer.WindowSetMode(
                mode == DisplayServer.WindowMode.Fullscreen
                    ? DisplayServer.WindowMode.Windowed
                    : DisplayServer.WindowMode.Fullscreen);
        }
    }
}
