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

#ifndef CIRCLE_H_
#define CIRCLE_H_

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

class UniversalDataReader;

/**
 *  Contains the Circle Behavior.
 *  Drives the vehicle in a circle at a set radius from a waypoint.
 *
 *  Circle.h should only be included by Circle.cpp
 *  Other classes should include CircleIF.h
 *
 *  \ingroup modules_controller
 */
class Circle : public Behavior
{
public:

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

    virtual ~Circle();

    /// Initialize function
    void initialize( void );

    /// Returns true when vehicle has "arrived"
    /// within the radius of 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:

    /// Starting angle of the vehicle around the circle.
    float startAngle_;

    /// One we've exceeded this angle around the circle, begin looking for a rotation.
    float thresholdAngle_;

    /// True if we have exceeded startAngle + threshold
    bool passedThreshold_;

    /// Desired Latitude
    float angleSetting_;

    /// Desired Latitude
    float latitudeSetting_;

    /// Desired Longitude
    float longitudeSetting_;

    /// Maximum error
    float maxErrorSetting_;

    /// Radius of the circle
    float radiusSetting_;

    /// If true, vehicle turns to port around the circle.
    bool turnToPortSetting_;

    /// Indicates initialization success
    bool initialized_;

    // Slate input setting variables

    /// angle of the circle to proceed through
    SettingReader *angleSettingReader_;

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

    // Maximum radial error: if outside this range, drive straight to the
    // circle perimeter
    SettingReader *maxErrorSettingReader_;

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

    /// radius of the circle
    SettingReader *radiusSettingReader_;

    /// if true, vehicle turns to port around the circle.
    SettingReader *turnToPortSettingReader_;

    // Slate input measurements

    /// Current platform latitude
    UniversalDataReader *latitudeReader_;

    /// Current platform longitude
    UniversalDataReader *longitudeReader_;

    // Slate output variables

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

    // Sets the bearing for HorizontalControl
    DataWriter *bearingCmdWriter_;

    // Sets the latitude for HorizontalControl
    DataWriter *latitudeCmdWriter_;

    // Sets the longitude for HorizontalControl
    DataWriter *longitudeCmdWriter_;


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


};

#endif /*CIRCLE_H_*/
