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

#ifndef AHRS_3DMGX3_H
#define AHRS_3DMGX3_H

#include "component/FailureMode.h"
#include "component/SyncComponent.h"
#include "io/LoadControl.h"
#include "io/UartStream.h"
#include "logger/Logger.h"

class UniversalDataReader;
class UniversalDataWriter;

/**
 *  Provides software interface to the Microstrain 3DMGX1 AHRS.
 *  Can also use SimSlate to provide simulated AHRS values when
 *  they are available.
 *
 *  AHRS_3DMGX3.h should only be included by AHRS_3DMGX3.cpp
 *  Other classes should include AHRS_3DMGX3IF.h
 *
 *  \ingroup modules_sensor
 */
class AHRS_3DMGX3 : public SyncSensorComponent
{
public:

    AHRS_3DMGX3( const Module* module );

    virtual ~AHRS_3DMGX3();

    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();

    void uninitialize();

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

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

    // scen configuraiton settings
    void readConfig();

    // Slate inputs
    UniversalDataReader* latitudeReader_;
    UniversalDataReader* longitudeReader_;

    // Slate outputs
    DataWriter* compassHeadingWriter_;
    UniversalDataWriter* magneticHeadingWriter_;
    UniversalDataWriter* trueHeadingWriter_;
    UniversalDataWriter* pitchWriter_;
    UniversalDataWriter* rollWriter_;
    UniversalBlobWriter* rotationMatrixWriter_;

    UniversalDataWriter* rollRateWriter_;
    UniversalDataWriter* pitchRateWriter_;
    UniversalDataWriter* yawRateWriter_;

    ConfigReader* magDeviationCfgReader_;
    ConfigReader* pitchOffsetCfgReader_;
    ConfigReader* rollOffsetCfgReader_;

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

    // Debugging outputs
    bool debug_;

    // Instance of load controller
    LoadControl loadControl_;

    Timespan ahrsTimeout_;
    Timestamp startTime_;

    // True if we have alerted user that we are using Simulator instead of hardware.
    bool usingSimWarned_;

    /// Deviation of this compass in the vehicle.
    /// compass orientation +/- deviation due to vehicle = Magnetic orientation
    /// magnetic orientation +/- variation from map = True orientation
    float magDeviation_;
    float magVariation_;

    /// Offset for mounting. In degrees.
    float pitchOffset_;
    float rollOffset_;

    // Multipler for angular rate vectors
    // Equals GyroGainScale from device (EEPROM address #130, nominally 8500) / 32768000
    float  gyroGain_;

    // Stores the current response from the modem
    char deviceResponse_[96];

    // Holds the communications device
    UartStream uart_;

    // Current fault
    FailureMode::FailType fault_;

    // Flips endian and converts 4 bytes to floating point
    float extractFloat( char * convertFloat );

    FailureMode::FailType readTemperature( float  &temperature );

    FailureMode::FailType readTransducers( float  &roll, float  &pitch, float  &magHeading,
                                           float  &rollRate, float  &pitchRate, float  &yawRate );


};

#endif /*AHRS_3DMGX3_H*/
