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

#ifndef WAYPOINT_H_
#define WAYPOINT_H_

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

class UniversalDataReader;

/**
 *  Contains the Waypoint Behavior/Command.
 *  Drives the vehicle towards a waypoint, using crosstrack error correction.
 *
 *  Waypoint.h should only be included by Waypoint.cpp
 *  Other classes should include WaypointIF.h
 *
 *  \ingroup modules_controller
 */
class Waypoint : public Behavior
{
public:

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

    virtual ~Waypoint();

    /// Initialize function
    void initialize( void );

    /// Returns true when vehicle has "arrived" at the waypoint
    bool isSatisfied();

    /// runs only if unsatisfied
    bool runIfUnsatisfied();

    /// The actual "payload" of the component
    void run();

    /// Uninit function
    void uninitialize( void );

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

protected:

    /// Desired Latitude
    double latitudeSetting_;

    /// Desired Longitude
    double longitudeSetting_;

    /// Desired Bearing
    float bearing_;

    /// Either a valid capture Radius or NaN
    float captureRadiusSetting_;

    /// If true, attempt to drive in water frame of reference (no attempt to fix for crosstrack errors,
    /// drive until calculated distance thru water is achieved). Can not be used with captureRadius
    int waterFrameSetting_;

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

    /// When in waterFrame mode, this is the value of platform_distance_wrt_sea_water
    /// when the endpoint is reached
    float endDistanceWrtSea_;

    /// Indicates initialization success
    bool initialized_;

    /// Indicates an actual lat/lon setting as opposed to one that is nan or one that isn't returned by the reader
    bool latlonSettingReal_;

    // Slate input setting variables

    /// radius of the circle that defines that the
    /// vehicle has reached the waypoint
    SettingReader *captureRadiusSettingReader_;

    /// distance from the nominal waypoint set by other settings.
    /// Must be combined with distanceDeltaBearing!
    SettingReader *distanceDeltaSettingReader_;

    /// bearing of distance from the nominal waypoint set by other settings.
    /// Must be combined with distanceDelta!
    SettingReader *distanceDeltaBearingSettingReader_;

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

    // Desired waypoint latitude
    SettingReader *latitudeSettingReader_;

    // Desired waypoint latitude delta from the current latitude
    // If specified with latitude, the two are added together
    SettingReader *latitudeDeltaSettingReader_;

    // Desired waypoint longitude
    SettingReader *longitudeSettingReader_;

    // Desired waypoint latitude delta from the current latitude
    // If specified with latitude, the two are added together
    SettingReader *longitudeDeltaSettingReader_;

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

    /// If true, attempt to drive in water frame of reference (no attempt to fix for crosstrack errors,
    /// drive until calculated distance thru water is achieved). Can not be used with captureRadius
    SettingReader* waterFrameSettingReader_;

    // Slate input measurements

    /// Current platform latitude
    UniversalDataReader *latitudeReader_;

    /// Current platform longitude
    UniversalDataReader *longitudeReader_;

    /// Distance vehicle has travelled through the water
    UniversalDataReader *distanceWrtSeaReader_;

    // Slate output variables

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

    // Sets the waypoint latitude for HeadingControl
    DataWriter *latitudeCmdWriter_;

    // Sets the waypoint longitude for HeadingControl
    DataWriter *longitudeCmdWriter_;

    // Computes the bearing to the waypoint
    DataWriter *bearingCmdWriter_;

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


};

#endif /*WAYPOINT_H_*/
