/** \file
 *
 *  Contains the Rowe_600LCM class declaration.
 *
 *  Rowe_600.h should only be included by Rowe_600LCM.cpp
 *  Other classes should include Rowe_600LCMIF.h
 *
 *  Copyright (c) 2014 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

// TODO: Following the apparent naming convention, perhaps this module should
// actually be called [ADCP_Rowe]. Nothing in the interface is specific to the
// 600 kHz nominal center frequency anyway.

#ifndef Rowe_600LCM_H
#define Rowe_600LCM_H

#include <lcm/lcm-cpp.hpp>
#include "lrauv-lcmtypes/marine-sensors/marine_sensors/bottom_track.hpp"
#include "lrauv-lcmtypes/marine-sensors/marine_sensors/vehicle_water_velocity.hpp"
#include "lrauv-lcmtypes/marine-sensors/marine_sensors/rowe_dvl.hpp"

#include "component/AsyncComponent.h"
#include "data/Matrix3x3.h"
#include "data/Point3D.h"
#include "data/Mtx.h"
#include "io/UartStream.h"
#include "io/LoadControl.h"
#include "logger/Logger.h"
#include "data/StrValue.h"

#include "sensorModule/Rowe_600LCMIF.h" // for Rowe_600LCMIF::MAX_SIZE_OF_ENSEMBLE

class UniversalDataWriter;

/**
 *  Provides software interface to the Rowe Rowe_600 DVL.
 *
 *  \ingroup modules_sensor
 */

class Rowe_600LCM : public AsyncComponent
{
public:

    Rowe_600LCM( const Module* module );

    virtual ~Rowe_600LCM();

//    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 start();
    }

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

    virtual 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.
    Rowe_600LCM( const Rowe_600LCM& old ); // disallow copy constructor

    void handleBottomTrackMessage( const lcm::ReceiveBuffer* rbuf, const std::string& chan, const marine_sensors::bottom_track* msg );
    void handleWaterSpeedMessage( const lcm::ReceiveBuffer* rbuf, const std::string& chan, const marine_sensors::vehicle_water_velocity* msg );
    void handleDVLMessage( const lcm::ReceiveBuffer* rbuf, const std::string& chan, const marine_sensors::rowe_dvl* msg );

    // Values of config variables for lcm bridge
    StrValue lcmChannelBottom_, lcmChannelWater_, lcmChannelDVL_, lcmApplication_, uartName_;
    int baudInt_;

    //*------------------- vehicle parameters --------------------------*/


    ///////////////////////////////////

    // initialize vehicle config variables
    bool loadParams( void );

    // scan configuration settings
    bool readConfig( void );

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

    // finally, write the data to the slate
    void writeData( void );

    void setAltitudeWritersInvalid( bool validity );
    void setSOGWritersInvalid( bool validity );
    void setWaterWritersInvalid( bool validity );

    // standard member parameters   TODO: should these be moved up to the superclass?
    bool debug_; // flag for debugging outputs
    bool loadAtStartup_; // To turn on/off without restart
    bool newBTData_, newWTData_, newDVLData_; // New data coming in for water/bottom track or DVL only
    LoadControl loadControl_; // the interface for the assigned load control board
    Timespan powerOnTimeout_; // timeout for powering down/up
    Timespan dvlDataTimeout_; // timeout for getting good (i.e. not nan) data from the DVL
    Timespan pausePeriod_; // pause period for Asynchronous component

    // device-specific member parameters
    Timestamp dataTimestamp_; // time the RTI preamble was successfully read
    Timespan sampleTime_;
    Timestamp startTime_; // time data request started

    float maxSpeedCfg_;
    float bottomTrackVelocityAccuracyCfg_;
    float waterTrackVelocityAccuracyCfg_;
    float altitudeAccuracyCfg_;


    // additional parameters for LRAUV software interface
    float altitude_;

    // Members for incoming data from instrument interface
    float beam1Range_, beam2Range_, beam3Range_, beam4Range_;
    double veloInstX_, veloInstY_, veloInstZ_;
    double wVeloInstX_, wVeloInstY_, wVeloInstZ_;

    Point3D velocityRelativeToGroundInVehicleFrame_;
    Point3D velocityRelativeToWaterInVehicleFrame_;

    // Config readers
    ConfigReader* altitudeAccuracyCfgReader_; // reads a float indicating the rated accuracy of the bottom track velocity
    ConfigReader* maxSpeedCfgReader_; // reads a float
    ConfigReader* bottomLcmChannelCfgReader_;
    ConfigReader* waterLcmChannelCfgReader_;
    ConfigReader* lcmApplicationCfgReader_;
    ConfigReader* bottomTrackVelocityAccuracyCfgReader_;
    ConfigReader* waterTrackVelocityAccuracyCfgReader_;
    ConfigReader* dvlLcmChannelCfgReader_;


    // Universal writers
    UniversalDataWriter* altitudeWriter_;

    UniversalDataWriter* xVelWrtGroundWriter_;
    UniversalDataWriter* yVelWrtGroundWriter_;
    UniversalDataWriter* zVelWrtGroundWriter_;
    UniversalDataWriter* xVelWrtSeaWriter_;
    UniversalDataWriter* yVelWrtSeaWriter_;
    UniversalDataWriter* zVelWrtSeaWriter_;

    UniversalBlobWriter* velocityWrtGroundWriter_;
    UniversalBlobWriter* velocityWrtWaterWriter_;

    DataWriter* alt1Writer_;
    DataWriter* alt2Writer_;
    DataWriter* alt3Writer_;
    DataWriter* alt4Writer_;

};
#endif /*Rowe_600LCM_H*/
