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

#ifndef WETLABSBB2FL_H
#define WETLABSBB2FL_H

#include "WetLabsBB2FLIF.h"

#include <vector>       // std::vector

#include "component/AsyncComponent.h"
#include "io/LoadControl.h"
#include "io/UartStream.h"
#include "logger/Logger.h"
#include "utils/BinFilter1D.h"

class UniversalDataWriter;

/**
 *  Provides software interface to the Wetlabs puck.
 *
 *  \ingroup modules_science
 */

class WetLabsBB2FL : public AsyncComponent
{
public:

    WetLabsBB2FL( const Module* module );

    virtual ~WetLabsBB2FL();

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

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

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

    /// Reads configuration
    void readConfig( void );

    /// Gets most recent data form device
    bool readData( void );

    /// Parses the header information sent back
    bool parseHeader( void );

    /// Parses the information sent back
    bool parse( void );

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

    /// Sends data to DataWriters
    void writeData( void );

    /// Updates the bin used for onboard binning
    void updateTemporalBin( void );

    /// Calculates bin statistics and writes to the slate
    void calculateAndReportTemporalBinStatistics( void );

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

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

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

    /// Holds the communications device
    UartStream uart_;

    /// Power
    LoadControl loadControl_;

    /// Time data request started
    Timestamp startTime_;

    /// Time the data was collected
    Timestamp dataTime_;

    /// Timeout for getting data
    Timespan timeout_;

    /// Outputs
    UniversalDataWriter* chlConcWriter_;
    UniversalDataWriter* cdomConcWriter_;

    DataWriter* backScat470Writer_;
    DataWriter* backScat650Writer_;
    DataWriter* output470Writer_;
    DataWriter* output650Writer_;
    DataWriter* outputChlWriter_;
    DataWriter* outputCdomWriter_;
    DataWriter* volScat470Writer_;
    DataWriter* volScat650Writer_;

    DataWriter* binMedianChlWriter_;
    DataWriter* binMeanChlWriter_;
    DataWriter* binVarianceChlWriter_;
    DataWriter* binMedianCdomWriter_;
    DataWriter* binMeanCdomWriter_;
    DataWriter* binVarianceCdomWriter_;

    /// Inputs
    UniversalDataReader* salinityReader_;

    ConfigReader* chlAccuracyCfgReader_;
    ConfigReader* cdomAccuracyCfgReader_;
    ConfigReader* darkCounts470CfgReader_;
    ConfigReader* darkCounts650CfgReader_;
    ConfigReader* darkCountsChlCfgReader_;
    ConfigReader* darkCountsCdomCfgReader_;
    ConfigReader* scaleFactor470CfgReader_;
    ConfigReader* scaleFactor650CfgReader_;
    ConfigReader* scaleFactorChlCfgReader_;
    ConfigReader* scaleFactorCdomCfgReader_;
    ConfigReader* serialCfgReader_;

    /// Calibration coefficients
    float chlConcAccuracy_;
    float cdomConcAccuracy_;
    float scaleFactor470_;
    float scaleFactor650_;
    float scaleFactorChl_;
    float scaleFactorCdom_;
    int darkCounts470_;
    int darkCounts650_;
    int darkCountsChl_;
    int darkCountsCdom_;

    /// Current number of samples to average
    int currentSamplesToAverage_;

    /// Container for history to use in temporal binning'
    BinFilter1D<float> chlBin_;
    BinFilter1D<float> cdomBin_;

    /// Serial number of this device
    Str serial_;

    /// Raw measurement for backscatter at 470nm
    int output470_;

    /// Raw measurement for backscatter at 650nm
    int output650_;

    /// Raw measurement for chl fluorescence
    int outputChl_;

    /// Raw measurement for CDOM flourescence
    int outputCdom_;

    /// Output variable
    float volScat470_;

    /// Output variable
    float backScat470_;

    /// Output variable
    float volScat650_;

    /// Output variable
    float backScat650_;

    /// Output variable
    float chlConc_;

    /// Output variable
    float cdomConc_;

    /// Debugging outputs
    bool debug_;
};

#endif /*WETLABSBB2FL_H*/
