#nullable enable
using System;

using IGP.UnitySDK.Models;

namespace IGP.UnitySDK
{
    /// <summary>
    /// Parse IGP launch arguments passed by the desktop client.
    /// </summary>
    public static class IGPLaunchArgsParser
    {
        public static bool TryParse(string[] args, out IGPLaunchOptions? options)
        {
            options = null;
            if (args == null || args.Length == 0)
            {
                return false;
            }

            var parsed = new IGPLaunchOptions();

            for (var i = 0; i < args.Length; i++)
            {
                var arg = args[i];
                if (string.IsNullOrWhiteSpace(arg))
                {
                    continue;
                }

                if (TryReadOption(args, ref i, "--arena-launch-ticket", out var launchTicket))
                {
                    parsed.launchTicket = launchTicket;
                    continue;
                }

                if (TryReadOption(args, ref i, "--arena-bootstrap-endpoint", out var bootstrapEndpoint))
                {
                    parsed.bootstrapEndpoint = bootstrapEndpoint;
                    continue;
                }

                if (TryReadOption(args, ref i, "--arena-bootstrap-secret", out var bootstrapSecret))
                {
                    parsed.bootstrapSecret = bootstrapSecret;
                    continue;
                }

                if (TryReadOption(args, ref i, "--igp-ipc-pipe", out var ipcPipeName))
                {
                    parsed.ipcPipeName = ipcPipeName;
                    continue;
                }

                if (TryReadOption(args, ref i, "--arena-auto-connect", out var autoConnect))
                {
                    parsed.autoConnect = IsTruthy(autoConnect);
                    continue;
                }

                if (TryReadOption(args, ref i, "--igp-app-id", out var appId) ||
                    TryReadOption(args, ref i, "--arena-app-id", out appId))
                {
                    if (int.TryParse(appId, out var parsedAppId) && parsedAppId > 0)
                    {
                        parsed.appId = parsedAppId;
                    }
                }
            }

            var hasHostedLaunchContext =
                !string.IsNullOrWhiteSpace(parsed.launchTicket) &&
                !string.IsNullOrWhiteSpace(parsed.bootstrapEndpoint) &&
                !string.IsNullOrWhiteSpace(parsed.bootstrapSecret);
            var hasAuthorizationPipe = !string.IsNullOrWhiteSpace(parsed.ipcPipeName);

            if (!hasHostedLaunchContext && !hasAuthorizationPipe)
            {
                return false;
            }

            options = parsed;
            return true;
        }

        private static bool TryReadOption(
            string[] args,
            ref int index,
            string optionName,
            out string value)
        {
            value = string.Empty;
            var arg = args[index];
            if (arg.StartsWith(optionName + "=", StringComparison.Ordinal))
            {
                value = arg.Substring(optionName.Length + 1);
                return true;
            }

            if (!string.Equals(arg, optionName, StringComparison.Ordinal))
            {
                return false;
            }

            var nextIndex = index + 1;
            if (nextIndex >= args.Length)
            {
                return false;
            }

            value = args[nextIndex];
            index = nextIndex;
            return true;
        }

        private static bool IsTruthy(string value)
        {
            return string.Equals(value, "1", StringComparison.Ordinal) ||
                   string.Equals(value, "true", StringComparison.OrdinalIgnoreCase) ||
                   string.Equals(value, "yes", StringComparison.OrdinalIgnoreCase);
        }
    }
}
