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

#ifndef SIMACOMMSRANGEHANDLER_H_
#define SIMACOMMSRANGEHANDLER_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 "SimACommsRangeGazebo.h"
class SimACommsRangeGazebo;
#endif


/// \brief SimACommsRangeHandler handles routing of simulated acomms range messages.
/// The class holds a range request/reply queue and bridges the SimSlate interface
/// to the simulated communication layer.
///
/// 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 range requests to the queue
/// * ReadOutgoingMessage:  transport layer access to read the next request in the queue
/// * WriteIncomingMessage: transport layer access to write range request results
/// * ReadIncomingMessage:  SimSlate accessor to read range request results
///
class SimACommsRangeHandler
{
    friend class SimSlate;
    friend class ExternalSim;
#ifdef __GAZEBO
    friend class SimACommsRangeGazebo;
#endif

private:

    /// Private constructor
    SimACommsRangeHandler()
    {}

    /// Private destructor
    ~SimACommsRangeHandler()
    {}

    /// Accessor function to add outgoing range requests to the queue
    /// \param[in] destination destination modem ID number
    /// \param[in] source source modem ID number
    /// \param[in] numPings the number of pings for the remote to return
    static bool WriteOutgoingMessage( int destination, int source, int numPings = 1 );

    /// Transport layer accessor function to read requests from the queue
    /// \param[in] destination returns destination modem ID number
    /// \param[in] source returns source modem ID number
    /// \param[in] numPings returns the number of requested return pings
    /// \param[in] msgID retruns unique message ID assigned to the interrogation
    static bool ReadOutgoingMessage( int& destination, int& source, int& numPings, int& msgID );

    /// Transport layer accessor function to write returning range request results
    /// \param[in] source modem ID number of the target
    /// \param[in] range slant range to the target
    /// \param[in] azimuth azimuth to the target
    /// \param[in] elevation elevation to the target
    /// \param[in] msgID unique message ID for this interrogation
    /// \param[in] rxTime message receive time
    static bool WriteIncomingMessage( int source, float range, float azimuth, float elevation, const Timestamp& rxTime, int msgId = 0 );

    /// Transport layer accessor function to write returning range request results
    /// \param[in] source modem ID number of the interrogated target
    /// \param[in] range returns the slant range to the target
    /// \param[in] azimuth returns theazimuth to the target
    /// \param[in] elevation returns theelevation to the target
    /// \param[in] msgID returns the unique message ID for this interrogation
    /// \param[in] rxTime returns the message receive time
    static bool ReadIncomingMessage( int source, float& range, float& azimuth, float& elevation, Timestamp& rxTime );

    /// 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] vehicleName string containing vehicle name
    static void SetLocalAddress( const Str& vehicleName );

    /// Defines the ping time interval for one-way ranging bursts
    static const float ONEWAY_MODE_PING_INTERVAL;

    /// Holds the range request queue
    static FastMap<const int, SimACommsRangeMessage*> RangeMessages_;

    /// Coordinates RangeMessages_ transactions
    static Mutex SimACommsRangeMutex_;

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

    /// Keeps track of unique message IDs
    static int acRangeMessageID_;

    /// Holds the vheicle name
    static Str vehicleName_;

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

};

#endif /* SIMACOMMSRANGEHANDLER_H_ */
