namespace inutralia.API
{
    using inutralia.Abstractions;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Net.Http;
    using System.Net;

    /// <summary>
    /// Interfaz genérico de comunicación con un Web Service
    /// </summary>
    public interface IWebService : IDataPersistenceService
    {
        /// <summary>
        /// Borra la información relativa a las credenciales
        /// </summary>
        void Reset();

        /// <summary>
        /// Establece las credenciales de acceso a la API
        /// </summary>
        /// <param name="username">Nombre del usuario accediendo a la API</param>
        /// <param name="password">Contraseña del usuario</param>
        void CredentialsSet(string username, string password);

        /// <summary>
        /// Registra un usuario en el servidor
        /// </summary>
        /// <param name="userName">Nombre del usuario solicitando registro</param>
        /// <param name="passWord">Contraseña del usuario solicitando registro</param>
        /// <param name="companyCode">Código de la compañía que solicita el registro</param>
        Task<HttpStatusCode?> RegisterUser(string userName, string passWord, string companyCode);

        /// <summary>
        /// Cambia la contraseña del usuario actual
        /// </summary>
        /// <param name="currPass">Contraseña actual (para verificación)</param>
        /// <param name="newPass">Nueva contraseña</param>
        Task<bool> PasswordChange(string currPass, string newPass);

        /// <summary>
        /// Obtiene de forma asíncrona una lista de elementos de cierto tipo
        /// </summary>
        /// <typeparam name="T">Tipo de datos de cada elemento</typeparam>
        /// <param name="path">Path de acceso al recurso de la API</param>
        /// <returns>Lista de elementos obtenidos</returns>
        Task<List<T>> RefreshListAsync<T>(string path);

        /// <summary>
        /// Petición directa al WebService
        /// </summary>
        /// <param name="method">Método HTTP de la petición</param>
        /// <param name="resourcePath">Path del recurso REST al cual acceder</param>
        /// <param name="data">Objeto a serializar en la petición</param>
        /// <returns>Respuesta del servidor</returns>
        Task<HttpResponseMessage> RawMessage(HttpMethod method, string resourcePath, object data = null);

        /// <summary>
        /// Petición directa al WebService (GET)
        /// </summary>
        /// <param name="resourcePath">Path del recurso REST al cual acceder</param>
        /// <param name="data">Objeto a serializar en la petición</param>
        /// <returns>Respuesta del servidor</returns>
        Task<HttpResponseMessage> RawMessage(string resourcePath, object data = null);

        /// <summary>
        /// Procesa la respuesta de una petición directa
        /// </summary>
        /// <typeparam name="T">Tipo de datos en el que convertir los datos de respuesta</typeparam>
        /// <param name="response">Respuesta devuelta por RawMessage</param>
        /// <param name="data">Objeto a poblar con los datos de respuesta. Se creará un nuevo objeto si este parámetro es null</param>
        /// <returns>El objeto poblado / creado. Si el status de la petición no es 2XX se devuelve null</returns>
        Task<T> ResponseProcess<T>(HttpResponseMessage response, T data = null) where T : class;

        /// <summary>
        /// Realiza un petición directa y procesa su respuesta
        /// </summary>
        /// <typeparam name="T">Tipo de datos en el que convertir los datos de respuesta</typeparam>
        /// <param name="method">Método HTTP de la petición</param>
        /// <param name="resourcePath">Path del recurso REST al cual acceder</param>
        /// <param name="input">Objeto a serializar en la petición</param>
        /// <param name="output">Objeto a poblar con los datos de respuesta. Se creará un nuevo objeto si este parámetro es null</param>
        /// <returns>El objeto poblado / creado. Si el status de la petición no es 2XX se devuelve null</returns>
        Task<T> RawMessage<T>(HttpMethod method, string resourcePath, object input = null, T output = null) where T : class;

    }
}
