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

#ifndef THRUSTERHE_H_
#define THRUSTERHE_H_

#include "EZServoServo.h"
#include "io/UartStream.h"

class UniversalDataWriter;

/**
 *  This is the device driver for the High Efficiency (HE) thruster controller.
 *
 *  ThrusterHE.h should only be included by ThrusterHE.cpp
 *  Other classes should include ThrusterHEIF.h
 *
 *  \ingroup modules_controller
 */
class ThrusterHE : public EZServoServo
{
public:

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

    ThrusterHE( const Module* module );
    virtual ~ThrusterHE();

    virtual void run();

    /// Do what needs to be done to run
    /// Similar to initialize, in old init/run/uninit sequence
    virtual RunState start();

    /// Might follow a STOP...START sequence
    virtual RunState starting();

    /// Pause for a short period (indicated by pauseTime)
    virtual RunState pause();

    /// Should eventually follow a PAUSE request: should set continueTime
    virtual RunState paused();

    /// Resume from PAUSE
    virtual RunState resume();

    /// Might follow a PAUSE...RESUME sequence
    virtual RunState resuming();

    /// Should eventually follow a START request or RESETTING
    virtual RunState runnable();

    /// Might occur in case of Error
    virtual RunState resetting()
    {
        return stop();
    }

    /// Initial state -- can be later followed by START
    virtual RunState stop();

    virtual RunState stopping();

    /// Initial state -- can be later followed by START
    virtual RunState stopped();

    // Shuts down motor controllers
    void uninitialize( void );

    /// Should return [myNamespace]::SIMULATE_HARDWARE, or [myNamespace]::POWER, etc
    virtual ConfigURI getConfigURI( ConfigOption configOption ) const;

private:

    // Instance of load controller
    LoadControl loadControl_;

    // The outputs themselves
    UniversalDataWriter* propOmegaWriter_;

    // The inputs
    DataReader* propOmegaReader_;

    ConfigReader* ratedSpeedCfgReader_;           // Holds the rated speed set in the AMT49406
    ConfigReader* deviationCfgReader_;            // Number of encoder ticks deviation allowed between expected and actual
    ConfigReader* allowableBadVelocityCfgReader_; // Allowable Number of bad velocity reads

    // returns true if data is requested from one of the readers
    bool isDataRequested();

    // returns true if a new position has been commanded
    bool isNeeded();

    typedef enum
    {
        INITIALIZE,   // Program basic initialization into EEPROM
        WAIT,         // Wait for EEPROM write to finish
        HOME,         // Do any centering/homing, etc if needed
        EXECUTE,      // Execute any stored programs
        VERIFY,       // Confirm operable and no errors
        DONE,         // Ready to run
    } StartupSequence;

    StartupSequence startup_;

    // The possible faults returned by the controller
    typedef enum
    {
        NO_ERROR,
        LOCK_DETECT_ERROR,
        ZERO_SPEED_ERROR,
        OVERCURRENT_ERROR,
        OVERTEMP_ERROR,
        SYSTEM_ERROR,
        OVERVOLTAGE_ERROR,
        UNRECOGNIZED_CMD_ERROR,
        BAD_FORM_ERROR
    } ControllerFault;

    // Most recent fault;
    ControllerFault thrusterHEFault_;

    // indicates whether things are ok to run
    bool ok_;

    // Debugging outputs
    bool debug_;

    // Stores the previous command
    float lastCmdPropOmega_;
    // Stores the commanded propeller rotational velocity
    float cmdPropOmega_;

    // Stores the commanded motor velocity
    float motorPosCmd_;

    // Stores the commanded velocity
    float controllerVelocityCmd_;

    int ratedSpeedCfg_;          // Holds the rated speed set in the AMT49406
    float deviationCfg_;
    int allowableBadVelocityCfg_; // Allowable Number of bad velocity reads

    //-----------------------------------------------------------------*/

    // Number of bad velocity reads
    int badVelocityCount_;

    // read vehicle config variables
    bool readConfig( void );

    // Current speed is within the bounds of what was commanded
    bool thrustSpdGood_;

    // Initialization routines. Returns true if initialization completed without error
    bool initThruster( void );

    // Query the controller for the speed at which it is spinning
    float getSpeed( void );

    // Checks for any faults that show up asynchronously between commands
    bool getControllerFaults( void );

    // Gets status and returns true if it's expected. Throws fault if not.
    int getOperationState( void );

    // Velocity good after the command has been issues and the thruster is run this long without fault
    Timespan velocityTimeout_;
    Timespan commandTimeout_; // Time it takes to respond to a FW/RV command

};

#endif /*THRUSTERHE_H_*/
