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

#ifndef OFFSHOREENVELOPE_H_
#define OFFSHOREENVELOPE_H_

#include "component/Behavior.h"
#include "controlModule/HorizontalControlIF.h"

class UniversalDataReader;

/**
 *  Contains the OffshoreEnvelope Behavior/Command.
 *  OffshoreEnvelope uses a offshore distance map to
 *  lookup the offshore distance of the current location.
 *  If the vehicle's offshore distance is within the specified
 *  max/min envelope, the command is satisfied. Otherwise,
 *  the vehcile is steered in a direction that puts its
 *  offshore distance back within the specified max/min
 *  envelope.
 *
 *  OffshoreEnvelope.h should only be included by OffshoreEnvelope.cpp
 *  Other classes should include OffshoreEnvelopeIF.h
 *
 *  \ingroup modules_guidance
 */
class OffshoreEnvelope : public Behavior
{
public:

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

    virtual ~OffshoreEnvelope();

    /// Initialize function
    void initialize( void );

    /// Read in the parameters for satisfied or runIfUnsatisfied: return true if OK.
    bool readParams( float &minOffshore, float& maxOffshore,
                     HorizontalControlIF::HorizontalMode& horizontalMode, float& speed,
                     float& latitude, float& longitude, float& offshoreDistance );

    /// Perform the satisfied: return true if envelope "satisfied"
    bool calcSatisfied( const float minOffshore, const float maxOffshore,
                        const float offshoreDistance );

    /// 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:

    Timestamp lastTimeInEnvelope_;

    // Slate input setting variables

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

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

    /// Current heading mode going to HeadingControl
    DataReader *horizontalModeReader_;

    /// Current waypoint latitude going to HeadingControl.
    /// Only applies if horizontalModeReader_'s value is WAYPOINT
    DataReader *latitudeCmdReader_;

    /// Current waypoint longitude going to HeadingControl.
    /// Only applies if horizontalModeReader_'s value is WAYPOINT
    DataReader *longitudeCmdReader_;

    /// Current bearing (radian) of the vehicle going to HeadingControl.
    /// Only applies if horizontalModeReader_'s value is HEADING
    DataReader *bearingCmdReader_;

    /// Current heading (radian) of the vehicle going to HeadingControl.
    /// Only applies if horizontalModeReader_'s value is HEADING
    DataReader *headingCmdReader_;

    /// Current speed (in m/s) of the vehicle going to SpeedControl
    DataReader *speedCmdReader_;

    // Slate input measurements

    /// Current location (latitude [degrees north], longitude [degrees east])
    UniversalDataReader *latitudeReader_;

    /// Current location (latitude [degrees north], longitude [degrees east])
    UniversalDataReader *longitudeReader_;

    //  Current distance from shore of vehicle;
    UniversalDataReader *offshoreDistanceReader_;

    //  Current orientation of vehicle;
    UniversalDataReader *orientationReader_;

    // Slate output variables

    /// Sets the depth mode for HeadingControl
    /// Default is HEADING.
    DataWriter *horizontalModeWriter_;

    /// Sets the heading for HeadingControl
    /// Default is zero.
    DataWriter *headingCmdWriter_;

    /// Sets the speed (in m/s) of the vehicle going to SpeedControl
    DataWriter *speedCmdWriter_;

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

};

#endif /*OFFSHOREENVELOPE_H_*/
