using System;
using TINK.Model.Device;

namespace TINK.Repository.Request
{
    /// <summary> Defines members to create requests.</summary>
    public interface IRequestBuilder
    {
        /// <summary> Holds the id denoting the merchant (TINK app). </summary>
        string MerchantId { get; }

        /// <summary> Gets the session cookie if user is logged in, an empty string otherwise. </summary>
        string SessionCookie { get; }

        /// <summary> Gets request to log user in. </summary>
        /// <param name="mailAddress">Mailaddress of user to log in.</param>
        /// <param name="password">Password to log in.</param>
        /// <param name="deviceId">Id specifying user and hardware.</param>
        /// <remarks>Requst which holds auth cookie <see cref="RequstBase.authcookie"/></remarks>
        string DoAuthorization(
            string mailAddress,
            string password,
            string deviceId);

        /// <summary> Logs user out. </summary>
        /// <param name="p_strMerchantId">Id of the merchant.</param>
        /// <param name="p_strSessionCookie"> Cookie which identifies user.</param>
        string DoAuthout();

        /// <summary> Get list of stations from file. </summary>
        /// <returns>Request to query list of station.</returns>
        string GetStations();

        /// <summary>Gets bikes available.</summary>
        /// <returns>Request to query list of bikes available.</returns>
        string GetBikesAvailable();

        /// <summary> Gets a list of bikes reserved/ booked by acctive user from Copri.</summary>
        /// <returns>Request to query list of bikes occupied.</returns>
        string GetBikesOccupied();

        /// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
        /// <param name="bikeId">Id of the bike to reserve.</param>
        /// <returns>Requst to reserve bike.</returns>
        string DoReserve(string bikeId);

        /// <summary> Gets request to cancel reservation. </summary>
        /// <param name="bikeId">Id of the bike to cancel reservation for.</param>
        /// <returns>Requst on cancel booking request.</returns>
        string DoCancelReservation(string bikeId);

        /// <summary> Request to get keys. </summary>
        /// <param name="bikeId">Id of the bike to get keys for.</param>
        /// <returns>Request to get keys.</returns>
        string CalculateAuthParameters(string bikeId);

        /// <summary> Gets the request for updating lock state for a booked bike. </summary>
        /// <param name="bikeId">Id of the bike to update locking state for.</param>
        /// <param name="location">Geolocation of lock when state change occurred.</param>
        /// <param name="state">New locking state.</param>
        /// <returns>Request to update locking state.</returns>
        string UpateLockingState(
            string bikeId, 
            LocationDto location,
            lock_state state,
            double batteryPercentage);

        /// <summary> Gets booking request request (synonym: booking == renting == mieten). </summary>
        /// <param name="bikeId">Id of the bike to book.</param>
        /// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
        /// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
        /// <returns>Request to booking bike.</returns>
        string DoBook(string bikeId, Guid guid, double batteryPercentage);

        /// <summary> Gets request for returning the bike. </summary>
        /// <param name="bikeId">Id of the bike to return.</param>
        /// <param name="location">Geolocation of lock when returning bike.</param>
        /// <returns>Requst on returning request.</returns>
        string DoReturn(string bikeId, LocationDto location, ISmartDevice smartDevice);

        /// <summary>
        /// Gets request for submiting feedback to copri server.
        /// </summary>
        /// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
        /// <param name="message">General purpose message or error description.</param>
        /// <param name="isBikeBroken">True if bike is broken.</param>
        string DoSubmitFeedback(string bikeId, string message = null, bool isBikeBroken = false);
    }

    /// <summary> Copri locking states</summary>
    public enum lock_state
    {
        locked,
        unlocked
    }

    /// <summary> Holds lockation info.</summary>
    public class LocationDto
    {
        public double Latitude { get; private set; }

        public double Longitude { get; private set; }

        /// <summary> Accuracy of location in meters.</summary>
        public double? Accuracy { get; private set; }

        public TimeSpan Age { get; private set; }

        public class Builder
        {
            public double Latitude { get; set; }

            public double Longitude { get; set; }

            public double? Accuracy { get; set; }

            public TimeSpan Age { get; set; }

            public LocationDto Build()
            {
                return new LocationDto { Latitude = Latitude, Longitude = Longitude, Accuracy = Accuracy, Age = Age };
            }
        }
    }
}