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

#ifndef POINT_H_
#define POINT_H_

#include "component/Behavior.h"

class UniversalDataReader;

/**
 *  Contains the Point Behavior/Command. Points the nose of the vehicle in the
 *  indicated direction.  Can point the vehicle towards a latitude, longitude,
 *  or both.  Can point towards a depth.
 *
 *  Point.h should only be included by Point.cpp
 *  Other classes should include PointIF.h
 *
 *  \ingroup modules_guidance
 */
class Point : public Behavior
{
public:

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

    virtual ~Point();

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

    // Slate input setting variables

    /// Desired absolute bearing to direct the vehicle to.
    /// If specified with Bearing, Yaw is added to the Bearing.
    /// This variable is used as a test for sequential completion if
    /// none of Latitude, Longitude, Northings, or Eastings are specified
    SettingReader *headingSettingReader_;

    /// Desired change in heading to direct the vehicle to.
    /// If specified with Bearing, Yaw is added to the Bearing.
    /// This variable is used as a test for sequential completion if
    /// none of Latitude, Longitude, Northings, or Eastings are specified
    SettingReader *headingDeltaSettingReader_;

    /// Desired rate of change in heading.
    /// If specified with Bearing, Yaw, Latitude, or Longitude, only active
    ///    until the desired heading change is achieved.
    /// Otherwise drives the vehicle in an arc.
    /// This variable is not used as a test for sequential completion
    SettingReader *headingRateSettingReader_;

    /// Desired rudder angle for the vehicle.
    /// If specified with Bearing, Yaw, Latitude, or Longitude, only active
    ///    until the desired heading change is achieved.
    /// Otherwise drives the vehicle in an arc.
    /// Overrides yawRate command.
    /// This variable is not used as a test for sequential completion
    SettingReader *rudderAngleSettingReader_;

    /// Desired latitude to achieve.  Nominally drives the vehicle due east or west.
    /// Can be specified with Longitude, Bearing, or Yaw to drive the vehicle diagonally.
    /// This variable is used as a test for sequential completion
    SettingReader *latitudeSettingReader_;

    /// Desired change in latitude to achieve.
    /// If specified with Latitude, added to the specified Latitude
    /// Otherwise added to the Latitude at initialization time
    /// This variable is used as a test for sequential completion
    SettingReader *latitudeDeltaSettingReader_;

    /// Desired change in latitude to achieve, expressed as a distance.
    /// If specified with Latitude, added to the specified Latitude
    /// Otherwise added to the Latitude at initialization time
    /// This variable is used as a test for sequential completion
    SettingReader *northingsDeltaSettingReader_;

    /// Desired longitude to achieve.  Nominally drives the vehicle due north or south.
    /// Can be specified with Latitude, Bearing, or Yaw to drive the vehicle diagonally.
    /// This variable is used as a test for sequential completion
    SettingReader *longitudeSettingReader_;

    /// Desired change in longitude to achieve.
    /// If specified with Longitude, added to the specified Longitude
    /// Otherwise added to the Longitude at initialization time
    /// This variable is used as a test for sequential completion
    SettingReader *longitudeDeltaSettingReader_;

    /// Desired change in longitude to achieve, expressed as a distance.
    /// If specified with Longitude, added to the specified Longitude
    /// Otherwise added to the Longitude at initialization time
    /// This variable is used as a test for sequential completion
    SettingReader *eastingsDeltaSettingReader_;

    /// Force update input settings every cycle
    SettingReader *forceUpdateSettingReader_;

    // Slate input measurements

    /// Current latitude of the vehicle
    UniversalDataReader *latitudeReader_;

    /// Current longitude of the vehicle
    UniversalDataReader *longitudeReader_;

    /// Current orientation of the vehicle
    UniversalDataReader *orientationReader_;

    // Slate output variables

    /// Sets the mode for HorizontalControl
    DataWriter *horizontalModeWriter_;

    /// Sets the specified latitude for HorizontalControl
    DataWriter *latitudeCmdWriter_;

    /// Sets the specified longitude for HorizontalControl
    DataWriter *longitudeCmdWriter_;

    /// Sets the specified bearing for HorizontalControl
    DataWriter *headingCmdWriter_;

    /// Sets the specified yaw rate for HorizontalControl
    DataWriter *headingRateCmdWriter_;

    /// Sets the specified rudder angle for HorizontalControl
    DataWriter *rudderAngleCmdWriter_;

    // Settings

    /// Desired latitude of the vehicle
    float latitudeSetting_;

    /// Desired longitude of the vehicle
    float longitudeSetting_;

    /// Desired orientation of the vehicle
    float headingSetting_;

    /// Desired yaw rate of the vehicle
    float headingRateSetting_;

    /// Desired rudder angle for the vehicle.
    float rudderAngleSetting_;

    // Initial Values

    /// Initial latitude of the vehicle
    float initialLatitude_;

    /// Initial longitude of the vehicle
    float initialLongitude_;

    /// Initial orientation of the vehicle
    float initialOrientation_;

    // Current Values

    /// Current Latitude of the vehicle
    float latitude_;

    /// Current Longitude of the vehicle
    float longitude_;

    /// Current Orientation of the vehicle
    float orientation_;

    /// Last orientation delta of the vehicle
    float lastOrientationDelta_;

    /// 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_;

    /// Forces update of input settings when true
    int forceUpdate_;

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

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

};

#endif /*POINT_H_*/
