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

#ifndef ZIGZAG_H_
#define ZIGZAG_H_

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

class UniversalDataReader;

/**
 *  Contains the ZigZag Behavior/Command.  This is a very
 *  simple routine that simply points the nose of the vehicle
 *  at the indicated waypoint, until the waypoint is reached.
 *  If a angle is specified, then the waypoiny is
 *  reached when the vehicle is within the specified radius
 *  of the waypoint.
 *
 *  /todo implement waypoint satisfaction by "passing" waypoint
 *
 *  ZigZag.h should only be included by ZigZag.cpp
 *  Other classes should include ZigZagIF.h
 *
 *  \ingroup modules_controller
 */
class ZigZag : public Behavior
{
public:

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

    virtual ~ZigZag();

    /// Initialize function
    void initialize( void );

    /// Returns true when vehicle is starting to turn
    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 Bearing
    float bearingSetting_;

    /// Desired Angle
    float angleSetting_;

    /// Current Heading
    double headingRead_;

    /// Next Heading Cmd
    double headingCmd_;

    /// Indicates initialization success
    bool initialized_;

    bool goingRight_;

    // True when we turn
    bool satisfied_;

    // True once we run once
    bool ranOnce_;

    // Slate input setting variables

    // Desired bearing
    SettingReader *bearingSettingReader_;

    // Desired angle
    SettingReader *angleSettingReader_;

    // Slate input measurements

    // Gets the horizontal mode for HorizontalControl
    DataReader *horizontalModeReader_;

    // Gets the heading for HorizontalControl
    DataReader *headingCmdReader_;

    // Gets the bearing for HorizontalControl
    DataReader *bearingCmdReader_;

    // Slate output variables

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

    // Sets the heading for HorizontalControl
    DataWriter *headingCmdWriter_;

    // Carries out behavior on parameters
    void writeCmds();

    // Determines if behavior is satisfied
    bool calcSatisfied();

    // Reads in behavior settings
    void readSettings( bool force );

    // Reads in parameters used by writeCmds and calcSatisfied
    bool calculate();

    // Sets value of going right
    // Returns true if changed, and ranOnce_ is true
    void setGoingRight( bool goingRight );

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


};

#endif /*ZIGZAG_H_*/
