/** \file
 *
 *  Contains the SimACommsDataHandler class declaration.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef SIMACOMMSDATAHANDLER_H_
#define SIMACOMMSDATAHANDLER_H_

#include <math.h>

#include "SimACommsMessage.h"
#include "units/Unit.h"
#include "utils/FastMap.h"
#include "utils/FlexArray.h"
#include "utils/Mutex.h"
#include "utils/Str.h"
#include "utils/Timestamp.h"

#ifdef __GAZEBO
#include "SimACommsDataGazebo.h"
class SimACommsDataGazebo;
#endif


/// \brief SimACommsDataHandler handles routing of simulated acomms data messages.
/// The class holds a incoming/outgoing msg queue and bridges the SimSlate interface
/// to the simulated communication layer (e.g., ExternalSim, or Gazebo transport).
///
/// The class will route traffic through the Igntion transport layer when present.
///
/// The natural progression of messages through the handler is:
///
/// * WriteOutgoingMessage: SimSlate accessor to add outgoing msgs to the queue
/// * ReadOutgoingMessage:  transport layer access to read the next outgoing msg from the queue
/// * WriteIncomingMessage: transport layer access to add incoming msgs to the queue
/// * ReadIncomingMessage:  SimSlate accessor to read incoming msgs from the queue
///
class SimACommsDataHandler
{
    friend class SimSlate;
    friend class ExternalSim;
#ifdef __GAZEBO
    friend class SimACommsDataGazebo;
#endif

private:

    /// Private constructor
    SimACommsDataHandler()
    {}

    /// Private destructor
    ~SimACommsDataHandler()
    {}

    /// Accessor function to add outgoing data messages to the queue
    /// \param[in] destination destination modem ID number
    /// \param[in] source source modem ID number
    /// \param[in] message the message data payload
    /// \param[in] maxDistance legacy for GobyModem
    /// \param[in] delay legacy for GobyModem
    /// \param[in] mediumSpeed legacy for GobyModem
    static void WriteOutgoingMessage( int destination, int source, const Str& message, float maxDistance = 5000.0f, float delay = 13.0f, float mediumSpeed = 1500.0f );

    /// Transport layer accessor function to read outgoing messages from the queue
    /// \param[in] destination returns destination modem ID number
    /// \param[in] source returns source modem ID number
    /// \param[in] message the message data payload
    /// \param[in] maxDistance legacy for GobyModem
    /// \param[in] delay legacy for GobyModem
    /// \param[in] mediumSpeed legacy for GobyModem
    static bool ReadOutgingMessage( int& destination, int& source, Str& message, float& maxDistance, float& delay, float& mediumSpeed );

    /// Transport layer accessor function to write incoming messages to the queue
    /// \param[in] destination destination modem ID number
    /// \param[in] source source modem ID number
    /// \param[in] message the message data payload
    static void WriteIncomingMessage( int destination, int source, const Str& message );

    /// Transport layer accessor function to read incoming messages from the queue
    /// \param[in] destination returns destination modem ID number
    /// \param[in] source returns source modem ID number
    /// \param[in] message the message data payload
    static bool ReadIncomingMessage( int& destination, int& source, Str& message );

    /// Sets the acoustic response timeout
    /// \param[in] acousticResponseTimeout timeout timespan (typically in seconds)
    static void SetAcousticResponseTimeout( const Timespan& acousticResponseTimeout );

    /// Sets the local address (triggers init Igntion transport topics)
    /// \param[in] localAddress local modem ID number
    static void SetLocalAddress( int localAddress );

    /// Holds the incoming message queue
    static FlexArray<SimACommsDataMessage*> IncomingMessages_;

    /// Holds the outgoing message queue
    static FlexArray<SimACommsDataMessage*> OutgoingMessages_;

    /// Coordinates message queue transactions
    static Mutex SimACommsDataMutex_;

    /// Holds the acoustic response timeout
    static Timespan acousticResponseTimeout_;

    /// Holds the local modem ID number
    static int localAddress_;

#ifdef __GAZEBO
    /// Holds the Gazebo transport interface
    static SimACommsDataGazebo ignAComms_;
#endif

};

#endif /* SIMACOMMSDATAHANDLER_H_ */
