/** \file
 *
 *  Contains the ExternalSim class declaration.
 *
 *  ExternalSim.h should only be included by ExternalSim.cpp
 *  Other classes should include ExternalSimIF.h
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef EXTERNALSIM_H_
#define EXTERNALSIM_H_

#include "SimHeadStruct.h"
#include "SimInitStruct.h"
#include "SimResultStruct.h"
#include "SimRunStruct.h"
#include "SimACommsTarget.h"

#include "component/SyncComponent.h"
#include "data/Location.h"
#include "data/Matrix6x6.h"
#include "data/Point3D.h"
#include "data/Point6D.h"
#include "io/SocketClient.h"
#include "utils/AuvMath.h"
#include "utils/Datum.h"
#include "utils/FastMap.h"
#include "utils/Timestamp.h"

class ConfigReader;
class UniversalDataReader;

/**
 *  Interfaces via TCP/IP with a SimDaemon to provide dynamic
 *  and environmental simulation of the vehicle.
 *
 *  ExternalSim.h should only be included by ExternalSim.cpp
 *  Other classes should include ExternalSimIF.h
 *
 *  \ingroup modules_simulator
 */
class ExternalSim : public SyncSimulatorComponent
{

public:
    /// Constructor.
    ExternalSim( const Module* module );

    /// Destructor.
    virtual ~ExternalSim();

    /// Initialize the simulator
    virtual void initialize( void );

    /// Run the simulation
    virtual void run( void );

    /// Uninitialize the simulation
    virtual void uninitialize( void );

private:

    /// The socket to the dynamic simulator
    SocketClient* socketClient_;

    /// The internet address of this machine. Combined with pid_ to form
    /// a unique identifer to send to the server.
    int addr_;
    /// The user id running this process. Combined with addr_ to form
    /// a unique identifer to send to the server.
    int pid_;

    /// Indicates wheter the external sim is running
    bool ok_;

    // write State to Slate
    virtual void publishState( float entrainedBuoyancy );

    // configuration readers
    ConfigReader* simDaemonServerCfgReader_;

    //*------------------- slate variables -----------------------*/

    DataWriter* latitudeWriter_;
    DataWriter* longitudeWriter_;
    DataWriter* eastingWriter_;
    DataWriter* northingWriter_;
    DataWriter* utmZoneWriter_;
    DataWriter* propThrustWriter_;
    DataWriter* propTorqueWriter_;
    DataWriter* netBuoyWriter_;
    DataWriter* forceXWriter_;
    DataWriter* forceYWriter_;
    DataWriter* forceZWriter_;
    DataWriter* positionXWriter_;
    DataWriter* positionYWriter_;
    DataWriter* positionZWriter_;
    DataWriter* positionRollWriter_;
    DataWriter* positionPitchWriter_;
    DataWriter* positionHeadingWriter_;
    DataWriter* positionXDotWriter_;
    DataWriter* positionYDotWriter_;
    DataWriter* positionZDotWriter_;
    DataWriter* rateUWriter_;
    DataWriter* rateVWriter_;
    DataWriter* rateWWriter_;
    DataWriter* ratePWriter_;
    DataWriter* rateQWriter_;
    DataWriter* rateRWriter_;
    DataWriter* homingSensorAddressWriter_;
    DataWriter* homingSensorRangeWriter_;
    DataWriter* homingSensorAzimWriter_;
    DataWriter* homingSensorElevWriter_;
    //DataWriter* utmZoneWriter_;
    //DataWriter* northernHemiWriter_;

    // AHRS specific parameters:
    // Default amplitude on additive noise (in radians)
    static const double DEFAULT_AHRS_NOISE_AMPLITUDE;
    double ahrsNoiseAmplitude_;
    // Slate inputs
    DataReader* ahrsNoiseAmplitudeReader_;

    //----------------------------------------------------------------
    // Depth specific parameters:
    // Default value for the depthadditive noise amplitude (in meters)
    static const double DEFAULT_DEPTH_NOISE_AMPLITUDE;
    double depthNoiseAmplitude_;
    // Slate inputs
    DataReader *depthNoiseAmplitudeReader_;

    //----------------------------------------------------------------
    // Tailcone specific parameters:
    // The inputs
    DataReader* propOmegaActionReader_;
    DataReader* elevatorAngleActionReader_;
    DataReader* rudderAngleActionReader_;
    DataReader* massPositionActionReader_;
    DataReader* buoyancyActionReader_;
    DataReader* dropWeightStateReader_;
    DataReader* propOmegaReader_;
    DataReader* elevatorAngleReader_;
    DataReader* rudderAngleReader_;
    DataReader* massPositionReader_;
    DataReader* buoyancyPositionReader_;

    UniversalDataReader* altitudeReader_;
    float altitude_;

    float buoyancyNeutralOffset_; // Value added to buoyancy in the ExternalSim to achieve "True" neutral
    float massPositionOffset_;    // Value added to mass position in the ExternalSim to achieve "True" zero pitch
    float entrainedAir_;          // Amount of entrained air in vehicle
    float bottomLockGone_;        // Altitude greater than this value results in loss of bottom lock simulated

    FastMap<const int, SimACommsTarget*> beaconMap_;
    Timespan homingSensorTatCfg_;    // Homing sensor turn-around time.
    int      numberOfHomingTragetsCfg_;
    bool     useGeographic_;

    /// number of extra variables in ocean model data
    int oceanModelVarCount_;

    /// names of extra variables in ocean model data
    Str* oceanModelVarNames_;

    /// units of extra variables in ocean model data
    const Unit** oceanModelVarUnits_;

    //----------------------------------------------------------------
    // Communications
    SimHeadStruct runHead_;
    SimHeadStruct commsHead_;
    SimRunStruct runParams_;
    char dataBuf_[ MAX( 2048, ( sizeof( SimHeadStruct ) + sizeof( SimRunStruct ) ) )];
    SimResultStruct results_;
};

#endif /*EXTERNALSIM_H_*/
