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


#ifndef CTD_SEABIRDLCM_H
#define CTD_SEABIRDLCM_H

#include <lcm/lcm-cpp.hpp>

#include "auv-shared/messaging/LcmNames.h"
#include "auv-shared/messaging/LcmUtils.h"
#include "lrauv-lcmtypes/marine-sensors/marine_sensors/seabird_gpctd_t.hpp"

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

#include "scienceModule/CTD_SeabirdLCMIF.h" // for CTD_SeabirdLCMIF::MAX_SIZE_OF_ENSEMBLE

class UniversalDataWriter;

/**
 *  Provides software interface to the CTD_SeabirdLCM.
 *
 *  \ingroup modules_science
 */

class CTD_SeabirdLCM : public AsyncComponent
{
public:

    CTD_SeabirdLCM( const Module* module );

    virtual ~CTD_SeabirdLCM();

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

    void handleCTDMessage( const lcm::ReceiveBuffer* rbuf, const std::string& chan, const marine_sensors::seabird_gpctd_t* msg );

    // Values of config variables for lcm bridge
    StrValue 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 );

    // Used to determine if Seabird should run all the time.
    void  isDepthNeeded( void );

    void preprocessData(); // Perform onboard processing and quality checks

    // finally, write the data to the slate
    void writeData( void );
    void updateTemporalBin(); // update the onboard binning
    void calculateAndReportTemporalBinStatistics(); // calculate statistics when bin is full

    void setWritersInvalid( bool validity );

    // standard member parameters   TODO: should these be moved up to the superclass?
    bool debug_; // flag for debugging outputs
    bool newCTDData_; // New data coming in
    bool getSimulatedData(); // Try reading data from the SimSlate
    bool depthNeeded_; // flag to determine if CTD should provide vehicle depth

    LoadControl loadControl_; // the interface for the assigned load control board
    Timespan powerOnTimeout_; // timeout for powering down/up
    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 conductivity_, temperature_, pressureDB_, depth_, salinity_, density_, oxygenFreq_, soundSpeed_;
    bool badConductivity_, badTemperature_, badPressure_, badSalinity_, badOxygenFreq_;

    float maxPressBound_;
    float minPressBound_;
    float maxSalinityBound_;
    float minSalinityBound_;

    // container for history to use in temporal binning
    size_t temporal_bin_count_;
    std::vector<float> temporal_bin_conductivity_;
    std::vector<float> temporal_bin_temperature_;
    std::vector<float> temporal_bin_salinity_;
    Timestamp binTime_;

    // Config readers
    ConfigReader* lcmApplicationCfgReader_;

    ConfigReader* maxPressBoundCfgReader_;
    ConfigReader* minPressBoundCfgReader_;
    ConfigReader* offsetCfgReader_;
    ConfigReader* maxSalinityBoundCfgReader_;
    ConfigReader* minSalinityBoundCfgReader_;

    UniversalDataReader* depthReader_;
    UniversalDataReader* latitudeReader_;
    DataReader* gfScanActiveReader_;

    DataWriter* binMedianConductivityWriter_;
    DataWriter* binMedianTemperatureWriter_;
    DataWriter* binMedianSalinityWriter_;

    DataWriter* oxygenFreqWriter_;

    // Universal writers
    UniversalDataWriter* densityWriter_;
    UniversalDataWriter* soundSpeedWriter_;
    UniversalDataWriter* depthWriter_;
    UniversalDataWriter* salinityWriter_;
    UniversalDataWriter* temperatureWriter_;
    UniversalDataWriter* conductivityWriter_;
    UniversalDataWriter* pressureWriter_;

};
#endif /*CTD_SeabirdLCM_H*/
