using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;

namespace YMhut.Box.Core.App;

public enum IndependentWindowKind
{
    Browser,
    Media
}

public sealed record IndependentWindowHostOptions(
    IndependentWindowKind Kind,
    string Title,
    string InitialUrl = "",
    string Root = "",
    string AssetsRoot = "")
{
    public const string HostSwitch = "--ymhut-window-host";
    public const string KindSwitch = "--kind";
    public const string TitleSwitch = "--title";
    public const string UrlSwitch = "--url";
    public const string RootSwitch = "--root";
    public const string AssetsRootSwitch = "--assets-root";

    public static IndependentWindowHostOptions Browser(string title, string initialUrl, AppPaths paths)
        => new(IndependentWindowKind.Browser, title, initialUrl, paths.Root, paths.Assets);

    public static IndependentWindowHostOptions Media(string title, AppPaths paths)
        => new(IndependentWindowKind.Media, title, string.Empty, paths.Root, paths.Assets);

    public IReadOnlyList<string> ToArguments()
    {
        var args = new List<string>
        {
            HostSwitch,
            KindSwitch,
            Kind.ToString().ToLowerInvariant(),
            TitleSwitch,
            Title
        };

        AddOptional(args, UrlSwitch, InitialUrl);
        AddOptional(args, RootSwitch, Root);
        AddOptional(args, AssetsRootSwitch, AssetsRoot);
        return new ReadOnlyCollection<string>(args);
    }

    public static bool TryParse(IEnumerable<string> args, [NotNullWhen(true)] out IndependentWindowHostOptions? options)
    {
        options = null;
        var tokens = args.Where(token => !string.IsNullOrWhiteSpace(token)).ToArray();
        if (!tokens.Any(token => string.Equals(token, HostSwitch, StringComparison.OrdinalIgnoreCase)))
        {
            return false;
        }

        var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        for (var index = 0; index < tokens.Length; index++)
        {
            var token = tokens[index];
            if (!token.StartsWith("--", StringComparison.Ordinal) || string.Equals(token, HostSwitch, StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }

            if (index + 1 < tokens.Length && !tokens[index + 1].StartsWith("--", StringComparison.Ordinal))
            {
                map[token] = tokens[++index];
            }
        }

        var kindText = Value(map, KindSwitch);
        if (!TryParseKind(kindText, out var kind))
        {
            return false;
        }

        var title = Value(map, TitleSwitch);
        if (string.IsNullOrWhiteSpace(title))
        {
            title = kind == IndependentWindowKind.Browser ? "Safe Browser" : "Media Player";
        }

        options = new IndependentWindowHostOptions(
            kind,
            title,
            Value(map, UrlSwitch),
            Value(map, RootSwitch),
            Value(map, AssetsRootSwitch));
        return true;
    }

    private static bool TryParseKind(string value, out IndependentWindowKind kind)
    {
        var normalized = value.Trim().ToLowerInvariant();
        kind = normalized switch
        {
            "browser" or "safe_browser" or "safe-browser" => IndependentWindowKind.Browser,
            "media" or "media_player" or "media-player" => IndependentWindowKind.Media,
            _ => default
        };

        return normalized is "browser" or "safe_browser" or "safe-browser" or "media" or "media_player" or "media-player";
    }

    private static string Value(IReadOnlyDictionary<string, string> map, string key)
        => map.TryGetValue(key, out var value) ? value : string.Empty;

    private static void AddOptional(ICollection<string> args, string key, string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return;
        }

        args.Add(key);
        args.Add(value);
    }
}
