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

#ifndef UNDOCK_H_
#define UNDOCK_H_

#include <vector>
#include "component/Behavior.h"
#include "DockIF.h"

class UniversalDataReader;

/**
 *  Contains the Undock Behavior/Command.
 *
 *  Undock.h should only be included by Undock.cpp
 *  Other classes should include UndockIF.h
 *
 *  \ingroup modules_guidance
 */
class Undock : public Behavior
{
public:

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

    virtual ~Undock();

    /// Initialize function
    void initialize();

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

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

    /// 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();

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

protected:

    /// Init internal member variables to default values
    void initializeVariables( void );

    // Slate input setting variables

    /// Undock depth
    ConfigReader *undockDepthCfgReader_;

    /// Time duration for determining if the vehicle is undocked
    ConfigReader *undockTimeoutCfgReader_;

    /// Range objective for undocking
    ConfigReader *undockRangeCfgReader_;

    /// Max time duration to keep thruster engaged in reverse to break apart from the dock
    ConfigReader *reverseThrustTimeoutCfgReader_;

    /// Report state transitions to shore when true
    ConfigReader *verboseCfgReader_;

    /// Vehicle surface threshold
    ConfigReader *surfaceThresholdCfgReader_;

    /// Mass shifter default position
    ConfigReader *massDefaultCfgReader_;


    // Slate input measurements

    /// Vehicle depth
    UniversalDataReader* depthReader_;

    /// Slant range to target
    DataReader *dockRangeReader_;

    /// Power interface to camera
    DataReader *samplePowerOnlyReader_;

    /// Power interface to camera
    DataReader *sampleNanoDvrReader_;

    /// Docking module state
    DataReader *dockingStateReader_;

    /// Docking module IR sensor reading
    DataReader *cablePresentReader_;

    // Slate output variables

    /// Sets the mode of the docking module
    DataWriter *dockingStateCmdWriter_;

    /// Sets the specified depth for Depth Control
    DataWriter *depthCmdWriter_;

    /// Sets the elevator angle for Depth Control
    DataWriter *elevatorAngleCmdWriter_;

    /// Sets the massPosition for Depth Control
    DataWriter *massPositionCmdWriter_;

    /// Commands the vehicle's speed
    DataWriter *speedCmdWriter_;

    /// Sets the mode for Depth Control
    DataWriter *verticalModeWriter_;


    // Settings

    /// Undock depth
    float undockDepthSetting_;

    /// Objective range for terminal guidace
    float undockRangeSetting_;

    /// Time duration for determining if the vehicle is no longer docked
    Timespan undockTimeoutSetting_;

    /// Max time duration the thruster will engage to break apart from the dock
    Timespan reverseThrustTimeoutSetting_;

    /// Speed to use for disengaging the dock
    float speedSetting_;

    /// Vehicle surface threshold
    float surfaceThresholdCfgSetting_;

    /// Mass shifter default position
    float massDefaultCfgSetting_;

    /// Time duration for determining if range reading is valid
    Timespan validRangeTimeout_;

    // Undock Values

    typedef enum
    {
        UNINITIALIZED,
        DETACH,
        REVERSE,
        WAIT,
        DETACHED,
        UNDOCKED
    } UndockMode;

    /// The current undock mode
    UndockMode undockMode_;

    /// Command the state of the docking module
    bool cmdDockState( DockIF::DockingState stateCmd );

    /// Power on the camera and lights
    bool powerCameraAndLights( void );

    /// Power on the camera
    bool powerCamera( void );

    /// Power on the camera lights
    bool powerLights( void );

    /// Check range to dock
    bool rangeUndocked( bool noRangeDefaultVal = true );

    /// Time of undocking
    Timestamp undockTime_;

    /// Time of reverse thrust engage
    Timestamp reverseThrustTime_;

    /// Vehicle range to the dock transponder
    float dockRange_;

    /// Indicates the docking module hardware is loaded and available
    bool dockingModuleLoaded_;

    /// Reflects the current state of the dockoing servo
    DockIF::DockingState dockingState_;

    /// Indicates obscuration across docking servo IR emitter
    bool cablePresent_;

    /// Indicates the LCB power interface component is loaded and available
    bool powerOnlyLoaded_;

    /// Indicates the camera is loaded and available
    bool cameraLoaded_;

    /// Indicates the state of undock timer
    bool timerArmed_;

    bool verbose_;

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

};

#endif /*UNDOCK_H_*/
