using System;
using Wayne.Lib;

namespace Wayne.ForecourtControl.OptBridge
{
    /// <summary>
    /// The OPT object is used to communicate with an outdoor payment terminal connected to the forecourt server.
    /// Only one client can control the interface, and the interface must be reserverd by the client before the write() method is accepted.
    /// OnDataRead is also only signalled to the client that owns the reservation.
    /// </summary>
    public interface IOpt
    {
        #region Properties
        /// <summary>
        /// Logical terminal number / filling position.
        /// </summary>
        int Id { get;}

        /// <summary>
        /// Current state of the connection to the terminal. The Connection state will only be either Connected when
        /// the terminal is online or Connecting if the terminal is not responding.
        /// </summary>
        DeviceConnectionState ConnectionState { get;}

        /// <summary>
        /// If the terminal is reserved, the clientId of the reserving IOptBridge client will be reported here. 
        /// If the terminal not is reserved, it will be 0.
        /// </summary>
        int ReservedByClientId { get;}

        #endregion

        #region Events

        /// <summary>
        /// Event signalling that the connection state of the terminal has changed.
        /// </summary>
        event EventHandler<ConnectionChangedEventArgs> OnConnectionStateChange;

        /// <summary>
        /// Fired when data has been read from the terminal. Only the client that has reserved the terminal will receive this event.
        /// </summary>
        event EventHandler<OptDataEventArgs> OnDataRead;

        #endregion

        #region Methods

        /// <summary>
        /// Reserves this device for exclusve control from this instance.
        /// </summary>
        /// <param name="reserveCompleted">Callback delegate that will be invoked on completion.</param>
        /// <param name="userToken">User token object that will be returned in the completion callback</param>
        void ReserveAsync(EventHandler<AsyncCompletedEventArgs> reserveCompleted, object userToken);

        /// <summary>
        /// Cancel device reservation. This command is only allowed after a successful call to ReserveAsync() by the same client.
        /// </summary>
        /// <param name="unreserveCompleted">Callback delegate that will be invoked on completion.</param>
        /// <param name="userToken">User token object that will be returned in the completion callback</param>
        void UnreserveAsync(EventHandler<AsyncCompletedEventArgs> unreserveCompleted, object userToken);

        /// <summary>
        /// The data is transparently sent to the terminal, only appending protocol specific information. If waitForSendOk=false,
        /// the request will complete as soon as the data has been sent to the forecourt server. If it is true, the request will 
        /// be complete after the data is actually sent to the terminal.
        /// </summary>        
        /// <param name="terminalData"></param>
        /// <param name="waitForSendOk">If this flag is set, the writeCompleted will not be invoked until the data is actually sent to the terminal.</param>
        /// <param name="writeCompleted"></param>
        /// <param name="userToken"></param>
        void WriteAsync(byte[] terminalData, bool waitForSendOk, EventHandler<OptWriteCompletedEventArgs> writeCompleted, object userToken);

        #endregion
    }
}