using System.Net;
using System.Text;
using FluentFTP;
using HeyRed.Mime;

namespace Shoko;

[Protocol("ftp")]
[Protocol("ftps")]
class FtpProtoHandler : ProtoHandler
{
    public FtpProtoHandler(Uri url)
    {
        URL = url;
    }

    public override void Load()
    {
        var file = URL.AbsolutePath;

        var conn = new FtpClient
        {
            Host = URL.Host,
            Port = URL.Port
        };

        if (URL.UserInfo.Length > 0)
        {
            var userinfo = URL.UserInfo.Split(":",2);
            var user = userinfo[0];
            var pass = userinfo.Length > 1 ? userinfo[1] : "";
            conn.Credentials = new NetworkCredential(user, pass);
        }

        if(URL.Scheme == "ftps")
        {
            conn.Config.EncryptionMode = FtpEncryptionMode.Explicit;
            conn.Config.ValidateAnyCertificate = true;
        }

        conn.Config.LogToConsole = true;
        conn.Config.LogHost = true;
        conn.Config.LogUserName = true;
        conn.Config.LogPassword = true;

        conn.Connect();

        MediaType = "text/plain"; // TODO: magic numbers
        Status = "OK";

        var info = conn.GetObjectInfo(file);

        if(info is not null)
        {
            switch(info.Type)
            {
                case FtpObjectType.File:
                    //Content = conn.OpenRead(file);
                    if(conn.DownloadBytes(out byte[] bytes, info.FullName))
                    {
                        Content = new MemoryStream(bytes);
                        MediaType = MimeGuesser.GuessMimeType(Content);
                    }
                    break;
                case FtpObjectType.Directory:
                    MediaType = "text/gemini";
                    var entries = conn.GetListing(info.FullName);
                    var str = "# "+file+"\r\n";

                    foreach(var entry in entries)
                    {
                        var path = entry.Name;
                        if(entry.Type == FtpObjectType.Directory) path += "/";
                        var target = new Uri(URL, path).ToString();
                        if(entry.Type == FtpObjectType.Link) target = new Uri(URL, info.LinkTarget).ToString();
                        str += string.Format("=>{0} {1}\r\n", target, path);
                    }

                    Content = new MemoryStream(Encoding.UTF8.GetBytes(str));
                    break;
                case FtpObjectType.Link:
                    MediaType = "text/gemini";
                    Content = new MemoryStream(Encoding.UTF8.GetBytes("=>"+new Uri(URL, info.LinkTarget).ToString()));
                    break;
            }
        }
        else
        {
            if(conn.DirectoryExists(file))
            {
                MediaType = "text/gemini";
                var entries = conn.GetListing(file);
                var str = "# "+file+"\r\n";

                foreach(var entry in entries)
                {
                    var path = entry.Name;
                    if(entry.Type == FtpObjectType.Directory) path += "/";
                    str += string.Format("=>{0} {1}\r\n", new Uri(URL, path).ToString(), path);
                }

                Content = new MemoryStream(Encoding.UTF8.GetBytes(str));
            }
            else
            {
                Content = new MemoryStream(Encoding.UTF8.GetBytes("file not found"));
                Status = "not found";
            }
        }

        Loaded = true;
    }
    public override void Render()
    {
    }
}