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

#ifndef GOTOSURFACE_H_
#define GOTOSURFACE_H_

#include "component/Behavior.h"

class UniversalDataReader;

/**
 *  Contains the GoToSurface Behavior/Command.  Simply
 *  sends the vehicle to the surface.  Satisfied when the vehicle
 *  has reached the surface.
 *
 *  GoToSurface.h should only be included by GoToSurface.cpp
 *  Other classes should include GoToSurfaceIF.h
 *
 *  \ingroup modules_guidance
 */
class GoToSurface : public Behavior
{
public:

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

    virtual ~GoToSurface();

    /// Initialize function
    void initialize( void );

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

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

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

    // Slate input setting variables

    /// Setting Readers
    SettingReader* depthRateSettingReader_;
    SettingReader* pitchSettingReader_;
    SettingReader* speedSettingReader_;
    SettingReader* surfaceTimeoutSettingReader_;

    // Slate input measurements

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

    // Current height above sea floor
    UniversalDataReader *altitudeReader_;

    // Current pitch of vehicle
    UniversalDataReader *pitchReader_;

    // Slate output variables

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

    // Sets Control variables
    DataWriter* depthRateCmdWriter_;
    DataWriter* pitchCmdWriter_;
    DataWriter* speedCmdWriter_;

    // Configuration readers
    ConfigReader* surfaceThresholdCfgReader_;
    ConfigReader* pitchLimitCfgReader_;
    ConfigReader* buoyancyPumpDepthCfgReader_;
    ConfigReader* massPositionLimitAftCfgReader_;
    ConfigReader* massBackOnGoToSurfaceCfgReader_;
    ConfigReader* pitchTimeoutCfgReader_;

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

    // indicates whether things are ok to run
    bool ok_;
    bool surfaceTimeoutReported_, pitchTimeoutReported_; // used to only report failures once

    ///*------------------- vehicle parameters --------------------------*/
    float surfaceThreshold_;
    float pitchLimit_;
    float buoyancyPumpDepth_;
    float massPositionLimitAft_;
    int shiftMassOnGoToSurface_;
    ///////////////////////////////////

    /// Settings
    float depthRateSetting_;
    float pitchSetting_;
    float speedSetting_;
    float pitchTimeoutSetting_;
    float surfacingTimeoutSetting_;

    // Time that behavior was started
    Timestamp surfaceStartTime_, pitchStartTime_;

    // Timeout for pitching up and overall attempt at surfacing before calc is satisfied and allowed to fall through.
    Timespan pitchTimeout_, surfacingTimeout_;

    // initialize vehicle config variables
    bool loadParams( void );

    // Returns true if there is sufficient altitude to turn up and pitch is responding within the timeout.
    bool checkPitchAndAltitude( void );

    void resetTimeouts( void );

};

#endif /*GOTOSURFACE_H_*/
