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

#ifndef KEEPSTATION_H_
#define KEEPSTATION_H_

#include "component/Behavior.h"
#include "data/Location.h"

class UniversalDataReader;

/**
 *  Contains the DepthEnvelope Behavior/Command
 *  If the vehicle's depth is within the specified
 *  max/min envelope, the command is satisfied. Otherwise,
 *  the vehicle is sent to a depth within the specified max/min
 *  envelope.
 *
 *  \todo add in Catherine's code to use other
 *  variables to specify the max/min limits.
 *
 *  DepthEnvelope.h should only be included by DepthEnvelope.cpp
 *  Other classes should include DepthEnvelopeIF.h
 *
 *  \ingroup modules_guidance
 */
class KeepStation : public Behavior
{
public:

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

    virtual ~KeepStation();

    /// Read behavior settings
    void readSettings( void );

    /// Initialize function
    void initialize( void );

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

    /// return true if vehicle within radius of waypoint
    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:

    // "Most Recent" variables
    double latitude_;
    double longitude_;

    // Slate input setting variables

    /// Desired latitude of the vehicle should be stationed at
    SettingReader *latitudeSettingReader_;

    /// Desired longitude the vehicle should stay stationed at
    SettingReader *longitudeSettingReader_;

    /// Desired radius around the latitude, longitude
    /// that the vehicle should stay stationed at
    SettingReader *radiusSettingReader_;

    /// Desired speed to get on station
    SettingReader *speedSettingReader_;


    /// Dynamic Control Speed Mode setting
    DataWriter *speedCmdWriter_;

    // Sets the heading mode for HeadingControl
    DataWriter *horizontalModeWriter_;

    // Sets the bearing cmd for HeadingControl
    DataWriter *headingCmdWriter_;

    /// Desired latitude of the behavior's stationing point
    double latitudeSetting_;

    /// Desired longitude of the behavior's stationing point
    double longitudeSetting_;

    /// Desired radius around the latitude, longitude
    /// that the behavior should will try to remain stationed at
    float radiusSetting_;

    /// Desired speed to get on station
    float speedSetting_;

    typedef enum
    {
        NOT_INITIALIZED = 0,
        REST = 1,
        GOTO_WAYPOINT = 2
    } KeepStationMode;

    /// The current mode the behavior is in
    KeepStationMode mode_;

    /// Latitude at the time of initialization
    float startLatitude_;

    /// Longitude at the time of initialization
    float startLongitude_;

    /// The desired latitude the behavior will try
    /// to acquire next if mode is GOTO_INITIAL_WAYPOINT
    /// or GOTO_NEW_REST_WAYPOINT
    double targetLatitude_;

    /// The desired longitude the behavior will try
    /// to acquire next if mode is GOTO_INITIAL_WAYPOINT
    /// or GOTO_NEW_REST_WAYPOINT
    double targetLongitude_;

    /// Have we learned all our initial settings?
    bool initialized_;

    /// Slope for crossing line (thru wapoint)
    float perpendicularSlope_;

    /// Is our starting point latitude > than the latitude of the starting
    /// longitude on the crossing line?
    bool startOverLine_;

    UniversalDataReader *latitudeReader_;
    UniversalDataReader *longitudeReader_;

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

};

#endif /* KEEPSTATION_H_ */
