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

#ifndef SIMACOMMSTARGET_H_
#define SIMACOMMSTARGET_H_


#include "SimResultStruct.h"
#include "logger/Logger.h"

/// \brief Defines a simulated acoustic transponder and services homing interrogations.
class SimACommsTarget
{

public:

    /// Constructor
    /// \param[in] beaconAddress local modem ID number for this target
    /// \param[in] beaconLat beacon transponder Latitude
    /// \param[in] beaconLon beacon transponder Longitude
    /// \param[in] beaconDepth beacon transponder depth
    /// \param[in] logger reference to logger instance
    SimACommsTarget( int beaconAddress, double beaconLat, double beaconLon, double beaconDepth, Logger& logger );

    /// Destructor
    ~SimACommsTarget();

    /// Returns homing data for this traget in the *interrogating* vehicle-frame of reference (Fwd-Stbd-Keel FSK)
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] range returns slant range to the target
    /// \param[in] azimuth returns azimuth to the target
    /// \param[in] elevation returns elevation to the target
    /// \param[in] useGeographic when true compute range/azimuth using a direct geodesic solution on Earth's ellipsoid,
    ///                          otherwise uses planner trig.
    void getHomingDataInVehicleFrame( const SimResultStruct& local, float& range, float& azimuth, float& elevation, bool useGeographic );

    /// Returns the slant range to this traget
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] range returns slant range to the target
    /// \param[in] useGeographic when true compute range using a direct geodesic solution on Earth's ellipsoid,
    ///                          otherwise uses planner trig.
    float getSlantRange( const SimResultStruct& local, bool useGeographic = true );

    /// Returns bearing to this traget in the navigation frame (NED)
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] useGeographic when true compute bearing using a direct geodesic solution on Earth's ellipsoid,
    ///                          otherwise uses planner trig.
    float getBearing( const SimResultStruct& local, bool useGeographic );

    /// Returns inclination to this traget in the navigation frame
    /// NOTE: inclination angle is *positive down, negitive up*
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] range slant range to the target
    float getInclination( const SimResultStruct& local, float slantRange );


    /// "Sends" an interrogation signal to get homing data for this traget. Projects TAT for return time.
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] numPings the number of pings for the beacon to return. numPings>1 results in 2 Hz update burst.
    /// \param[in] msgID unique message ID for this interrogation
    /// \param[in] tatDelay transponder turn-around-time dely config
    /// \param[in] speedOfSound speed of sound though the medium
    void ping( const SimResultStruct& local, int numPings, int msgID, Timespan& tatDelay, float speedOfSound = 1500.0f );


    /// "Returns" homing data for this contact in response to an interrogation signal
    /// \param[in] local reference to SimResultStruct containing all position data for the *interrogating* vehicle
    /// \param[in] source returns the local modem ID number for this target
    /// \param[in] range returns slant range to the target (meter)
    /// \param[in] azimuth returns azimuth to the target (rad;+ stbd)
    /// \param[in] elevation returns elevation to the target (rad;+ down)
    /// \param[in] msgID returns the unique message ID for this interrogation
    /// \param[in] rxTime returns response receive time
    /// \param[in] useGeographic when true compute range/azimuth using a direct geodesic solution on Earth's ellipsoid,
    ///                          otherwise uses planner trig.
    int respond( const SimResultStruct& local, int& source, float& range, float& azimuth, float& elevation, int& msgID, Timestamp& rxTime, bool useGeographic = true );

    /// True when response homing data is "received"
    bool responseReady( void );

    /// Holds the local modem ID number for this target
    int address_;

private:

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

    /// Beacon transponder Lat/Lon position (radians)
    double lat_, lon_;

    /// Beacon transponder depth (m, positive down)
    double depth_;

    /// Beacon transponder UTM position (for planner trig option)
    double bcnN_, bcnE_;

    /// Holds the number of pings requested by interrogation
    int numPingsRequested_;

    /// Holds the number of pings returned per interrogation
    int numPingsSent_;

    /// Holds the unique message ID for interrogation being serviced
    int msgID_;

    /// Holds the projected turnaround time (travel time in the water) per interrogation
    Timespan homingTat_;

    /// Marks the time of last response
    Timestamp txTime_;

};

#endif /* SIMACOMMSTARGET_H_ */
