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


#ifndef WetLabsUBAT_H
#define WetLabsUBAT_H


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


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

class WetLabsUBAT : public AsyncComponent
{
public:

    WetLabsUBAT( const Module* module );

    ~WetLabsUBAT();

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

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

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

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

    /// Resume from PAUSE
    RunState resume();

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

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

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

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

    RunState stopping();

    /// Initial state -- can be later followed by START
    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.
    WetLabsUBAT( const WetLabsUBAT& old ); // disallow copy constructor

    /// Async thread cycle period
    static const Timespan PERIOD;

    /// Reads the component's configuration settings
    bool readConfig( void );

    /// Reads device ASCII data stream
    bool readRecord( void );

    /// Parses device ASCII data stream
    bool parseRecord( void );

    /// Processes device data
    void processRecord( void );

    /// Writes data to the Slate
    void writeData( void );

    /// Confirms device serial number matches config
    bool checkSerial( const char* serial );

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

    /// Reads data from the SimSlate
    bool getSimulatedData();

    /// Max device messages allowed in the buffer
    static const unsigned short MAX_DEVICE_MSG_QUEUE_SIZE;

    /// Number of values expected in device message
    static const unsigned short DEVICE_MSG_HEADER_NUM;

    /// Offset of the UBAT record number
    static const unsigned short RECORD_NUM_OFFSET;

    /// Offset of the calibration coefficient for HV step header
    static const unsigned short HV_STEP_CAL_OFFSET;

    /// Offset of the average bioluminescence header
    static const unsigned short AVG_BIOLUM_OFFSET;

    /// Offset of the flow RPM header
    static const unsigned short FLOW_RPM_OFFSET;

    /// Offset of the 60 Hz digitized raw A/D counts headers
    static const unsigned short RAW_AD_DATA_OFFSET;

    /// Max byte size for device response
    static const unsigned int MAX_DEVICE_RESPONSE_SIZE = 512;

    /// Stores the current response from the device
    char deviceResponse_[MAX_DEVICE_RESPONSE_SIZE + 1];

    // Configuration inputs
    ConfigReader* flowrateCalCoeffCfgReader_;
    ConfigReader* minFlowrateCfgReader_;
    ConfigReader* serialCfgReader_;

    // Slate inputs
    DataReader* enableUbatReader_;

    // Slate outputs
    DataWriter* avgBiolumWriter_;
    DataWriter* enableUbatWriter_;
    DataWriter* flowRateWriter_;
    DataWriter* hvStepCalCoeffWriter_;
    DataWriter* recordNumberWriter_;

    BlobWriter* rawADCountsWriter_;

    /// Serial number of this device
    Str deviceSerialNumber_;

    /// Holds the communications device
    UartStream uart_;

    /// Power interface
    LoadControl loadControl_;

    /// Power down/up timeout
    Timespan powerOnTimeout_;

    /// Time the RTI preamble was successfully read
    Timestamp dataTimestamp_;

    /// Time data request started
    Timestamp startTime_;

    /// Timeout for getting data
    Timespan sampleTimeout_;

    /// Time of last nominal flow rate sample
    Timestamp flowTime_;

    /// Average bioluminescence (photons s-1)
    float avgBiolum_;

    /// UBAT message record number
    int recordNum_;

    /// Calibration coefficient for HV step (photons s-1)
    float hvStepCalCoeff_;

    /// Flow rate calibration coefficient
    float flowrateCalibCoeff_;

    /// Minimum flowrate threshold
    float minFlowrateThreshold_;

    /// Measured flowrate
    float flowRate_;

    /// Measured flowrate in RPM
    int flowRPM_;

    /// Holds 60 Hz digitized raw A/D counts
    int rawADCounts_[WetLabsUBATIF::RAW_AD_DATA_SIZE];

    /// Indicates whether the comp should turn on/off without restart
    bool loadAtStartup_;

    /// flag for debugging outputs
    bool debug_;
};

#endif /* WetLabsUBAT_H */
