using System;
using System.Threading.Tasks;
using Capnp.Rpc;
using FabAccessAPI.Exceptions;
using FabAccessAPI.Schema;

namespace FabAccessAPI
{
    /// <summary>
    /// Service to connect to a server and maintain the connection
    /// </summary>
    public interface IAPI
    {
        #region Information about a connection and the server
        /// <summary>
        /// State of the conneciton, is the API-Service connecting to a server
        /// </summary>
        bool IsConnecting { get; }

        /// <summary>
        /// State of the conneciton, is the API-Service connected to a server
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// Information about the connection
        /// </summary>
        /// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connected to a server </exception>
        ConnectionData ConnectionData { get; }

        /// <summary>
        /// Information about the server
        /// Is only avalible if the API-Service is connected
        /// </summary>
        /// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
        ServerData ServerData { get; }
        #endregion

        #region Methods to connect to server
        /// <summary>
        /// Connect to server with ConnectionData
        /// If connection lost, the API-Server will try to reconnect
        /// </summary>
        /// <param name="connectionData"> Data to establish a connection to a server </param>
        /// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
        /// <exception cref="AuthenticationException"> When API-Service can connect to a server but can not authenticate </exception>
        /// <exception cref="InvalidOperationException"> When API-Service is allready connected </exception>
        Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null);

        /// <summary>
        /// Disconnect from a server
        /// </summary>
        /// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connect </exception>
        Task Disconnect();

        /// <summary>
        /// Try to connect to a server and get ServerData
        /// The connection is not maintained
        /// </summary>
        /// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
        Task<ServerData> TryToConnect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null);
        #endregion

        #region Session
        /// <summary>
        /// Get session after connection
        /// </summary>
        /// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
        Session Session { get; }
        #endregion

        #region Events
        /// <summary>
        /// Event on changes in connection status
        /// </summary>
        event EventHandler<ConnectionStatusChanged> ConnectionStatusChanged;

        /// <summary>
        /// Unbind all handlers from EventHandler<ConnectionStatusChanged>
        /// </summary>
        void UnbindEventHandler();
        #endregion
    }
}