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

#ifndef ALTITUDEENVELOPE_H_
#define ALTITUDEENVELOPE_H_

#include "component/Behavior.h"

class UniversalDataReader;

/**
 *  Contains the AltitudeEnvelope Behavior/Command
 *  If the vehicle's altitude is within the specified
 *  max/min envelope, the command is satisfied. Otherwise,
 *  the vehicle is sent to a depth where its altitude
 *  should be within the specified max/min envelope.
 *
 *  AltitudeEnvelope.h should only be included by AltitudeEnvelope.cpp
 *  Other classes should include AltitudeEnvelopeIF.h
 *
 *  \ingroup modules_guidance
 */
class AltitudeEnvelope : public Behavior
{
public:

    AltitudeEnvelope( const Str& prefix,  const Module* module );

    virtual ~AltitudeEnvelope();

    /// Initialize function
    void initialize( void );

    /// Just do the run: ignore the results of the satisfied
    void run();

    /// Just do the satisfied: return true if envelope "satisfied"
    bool isSatisfied();

    /// Do the run, and return true if envelope "satisfied"
    bool runIfUnsatisfied();

    /// Uninit function
    void uninitialize( void );

    /// Mission Component factory interface
    static Behavior* CreateBehavior( const Str& prefix, const Module* module );

protected:

    /// Config setting readers
    ConfigReader* pitchLimitCfgReader_;
    ConfigReader* maxDiveRateCfgReader_;
    ConfigReader* maxBuoyDiveRateCfgReader_;


    // Current control commands

    /// Current vertical control depth mode
    DataReader *verticalModeReader_;

    /// Current speed control speed command
    DataReader *speedCmdReader_;

    // Behavior setting readers

    /// Desired minimum height above sea floor for the vehicle
    SettingReader *minAltitudeSettingReader_;

    /// Desired maximum height above sea floor for the vehicle
    SettingReader *maxAltitudeSettingReader_;

    /// Desired maximum depth to ignore altitude inputs for the vehicle
    SettingReader *maxDepthIgnoreSettingReader_;

    /// Desired up/down depthRate of the vehicle
    SettingReader *depthRateSettingReader_;

    /// Desired up depthRate of the vehicle
    SettingReader *upDepthRateSettingReader_;

    /// Desired down depthRate of the vehicle
    SettingReader *downDepthRateSettingReader_;

    /// Desired up/down pitch of the vehicle
    SettingReader *pitchSettingReader_;

    /// Desired up pitch of the vehicle
    SettingReader *upPitchSettingReader_;

    /// Desired down pitch of the vehicle
    SettingReader *downPitchSettingReader_;

    // Measurements

    /// Current height above sea floor
    UniversalDataReader *altitudeReader_;

    /// Current depth (in meter from sea surface -- positive down)
    UniversalDataReader *depthReader_;

    // Vertical Control Commands

    /// Sets the vertical mode for vertical control
    DataWriter *verticalModeWriter_;
    DataWriter *elevatorAngleCmdWriter_;
    DataWriter *massPositionCmdWriter_;

    /// Sets the depth rate for Vertical Control
    DataWriter *depthRateCmdWriter_;

    /// Sets the pitch for Vertical Control
    DataWriter *pitchCmdWriter_;

    // Initialization variables
    float minAltitude_;

    float maxAltitude_;

    float maxDepthIgnore_;

    /// Desired down depthRate of the vehicle
    float downDepthRateSetting_;

    /// Desired up depthRate of the vehicle
    float upDepthRateSetting_;

    /// Desired down pitch of the vehicle
    float downPitchSetting_;

    /// Desired up pitch of the vehicle
    float upPitchSetting_;

    /// Maximum dive rate of the vehicle
    float maxDiveRate_;

    /// Maximum dive rate of the vehicle under only buoyancy control
    float maxBuoyDiveRate_;

    /// Current speed cmd
    float speedCmd_;

    /// True if altitude is inactive
    int inactiveAltitudeCount_;

    /// Read in the parameters for satisfied or runSatisfied: return true if OK.
    bool readParams( float& altitude, float& depth );

    /// Perform the satisfied: return true if envelope "satisfied"
    bool calcSatisfied( const float& altitude, const float& depth );

    // Reads in configuration settings
    void readConfig();

    // Reads in behavior settings
    void readSettings( bool force );

    // If depthRate is nan, set to appropriate max dive rate.
    float adjustDepthRate( float depthRate, bool goDown );

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    AltitudeEnvelope( const AltitudeEnvelope& old ); // disallow copy constructor

};



#endif /*ALTITUDEENVELOPE_H_*/
