using Capnp.Rpc;
using FabAccessAPI;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace FabAccessAPI_Test
{
    [TestFixture, Order(0)]
    public class Connection_Test
    {
        const string TESTSERVER = "bffh.lab.bln.kjknet.de";
        const int TESTSERVER_PORT = 59666;

        private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        [TestCase(TESTSERVER, TESTSERVER_PORT)]
        public async Task Connect(string host, int port)
        {
            TcpRpcClient tcpRpcClient = new TcpRpcClient();
            tcpRpcClient.InjectMidlayer((tcpstream) =>
            {
                var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback));
                try
                {
                    sslStream.AuthenticateAsClient("bffhd");
                    return sslStream;
                }
                catch (AuthenticationException)
                {
                    sslStream.Close();
                    throw;
                }
            });
            tcpRpcClient.Connect(host, port);
            await tcpRpcClient.WhenConnected;

            Connection connection = new Connection(tcpRpcClient);
        }

        [TestCase(TESTSERVER, TESTSERVER_PORT, "Admin1", "secret")]
        public async Task Authenticate_PLAIN(string host, int port, string username, string password)
        {
            TcpRpcClient tcpRpcClient = new TcpRpcClient();
            tcpRpcClient.InjectMidlayer((tcpstream) =>
            {
                var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback));
                try
                {
                    sslStream.AuthenticateAsClient("bffhd");
                    return sslStream;
                }
                catch (AuthenticationException)
                {
                    sslStream.Close();
                    throw;
                }
            });
            tcpRpcClient.Connect(host, port);
            await tcpRpcClient.WhenConnected;

            Connection connection = new Connection(tcpRpcClient);
            await connection.Auth("PLAIN", new Dictionary<string, object>(StringComparer.Ordinal) { { "Username", username }, { "Password", password } });

            Assert.IsNotNull(connection.Session);
        }
    }
}