using System.Diagnostics;
using System.Reflection;
using System.Text;

namespace Shoko;

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
class ProtocolAttribute : Attribute
{
    public string Protocol;
    public ProtocolAttribute(string proto)
    {
        Protocol = proto;
    }
}

class ProtoHandler
{
    public Tab CurrentTab;
    public Uri URL;
    public string MediaType;
    public Stream Content;
    public string Status;
    public bool Loaded = false;
    public int LoadedBytes = 0;
    public int TotalBytes = 0;
    public IEnumerable<KeyValuePair<string,IEnumerable<string>>> Headers;
    public IEnumerable<KeyValuePair<string,string>> MediaTypeParams;
    public ProtoHandler()
    {

    }
    public ProtoHandler(Uri url)
    {
        URL = url;
    }
    public virtual void Load()
    {
        Content = new MemoryStream(Encoding.UTF8.GetBytes("error: no handler for this scheme"));
        MediaType = "text/plain";
        Loaded = true;
    }

    public virtual void Render()
    {
        Gui.Button("Open with external program", ()=>{
            try
            {
                if(OperatingSystem.IsLinux())
                    Process.Start("xdg-open", URL.ToString());
                else if(OperatingSystem.IsMacOS())
                    Process.Start("open", URL.ToString());
                else if(OperatingSystem.IsWindows())
                    Process.Start(URL.ToString());
            }
            catch{}
        });
    }

    public virtual void MenuBar()
    {
    }

    /// <summary>
    /// Get the appropriate protocol handler for the URL
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static ProtoHandler GetHandler(Uri url)
    {
        var proto = new UriBuilder(url).Scheme;
        var type = Assembly.GetAssembly(typeof(ProtoHandler)).GetTypes()
            .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(ProtoHandler)) && t.GetCustomAttributes<ProtocolAttribute>().Any(x => x.Protocol == proto))
            .SingleOrDefault(typeof(ProtoHandler));
        return (ProtoHandler)Activator.CreateInstance(type, url);
    }

    public static ProtoHandler GetHandler(string url)
    {
        return GetHandler(new Uri(url));
    }

    public static string[] SupportedProtos
    {
        get
        {
            return Assembly.GetAssembly(typeof(ProtoHandler)).GetTypes()
                .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(ProtoHandler)))
                .SelectMany(t => t.GetCustomAttributes<ProtocolAttribute>().Select(x => x.Protocol))
                .ToArray();
        }
    }
}