using Capnp.Rpc;
using FabAccessAPI.Schema;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace FabAccessAPI {
    class Connection {
        private TcpRpcClient? _rpcClient = null;
        private IBootstrap? _bootstrapCap = null;
        private AuthUser? _authUser = null;
        private Auth? _auth = null;
        private Machines? _machines = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rpcClient">Should be an already configured and connected TcpRpcClient</param>
        public Connection(TcpRpcClient rpcClient) {
            _rpcClient = rpcClient;
            _bootstrapCap = _rpcClient.GetMain<IBootstrap>();
        }

        /// <summary>
        /// Authenticate this connection.
        /// Calling this more then once is UB
        /// </summary>
        /// <param name="mech">The desired authentication mechanism</param>
        /// <param name="kvs">Key-Value data specific to the mechanism</param>
        /// <returns></returns>
        async Task Auth(string mech, Dictionary<string, object> kvs) {
            _auth = new Auth(await _bootstrapCap.Auth());
            var mechs = await _auth.GetMechanisms().ConfigureAwait(false);
            Console.WriteLine("The Server supports the following auth mechs:");
            Console.Write(mechs);

            // TODO: Check that the requested auth mech is actually available.

            await _auth.Authenticate(mech, kvs).ConfigureAwait(false);
        }

        /// <summary>
        /// Get a wrapped capability to interact with machines
        /// </summary>
        /// <returns>A wrapped capability to interact with machines</returns>
        async Task<Machines> AccessMachines() {
            _machines ??= new Machines((await _bootstrapCap.Machines().ConfigureAwait(false)));
            return _machines;
        }
    }
}