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

#ifndef WETLABSSEAOWL_UV_A_H
#define WETLABSSEAOWL_UV_A_H

#include "WetLabsSeaOWL_UV_AIF.h"

#include <vector>       // std::vector

#ifdef __arm__
#include "component/AsyncComponent.h"
#else
#include "component/SyncComponent.h"
#endif
#include "io/LoadControl.h"
#include "io/UartStream.h"
#include "logger/Logger.h"

class UniversalDataWriter;

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

class WetLabsSeaOWL_UV_A
#ifdef __arm__
    : public AsyncComponent
#else
    : public SyncSensorComponent
#endif
{
public:

    WetLabsSeaOWL_UV_A( const Module* module );

    virtual ~WetLabsSeaOWL_UV_A();

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

    bool readConfig();

    // Parses the information sent back
    bool parse( char* trimmedDeviceResponse );

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

    // Sends data to DataWriters
    void writeData();

    static const unsigned short MAX_DEVICE_MSG_QUEUE_SIZE = 10;
    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 runnable cycle started
    Timestamp runTime_;

    /// Timeout for getting data
    Timespan timeout_;

    /// How often to run the loop when paused.
    Timespan pausePeriod_;

    /// Duration of runnable cycle
    Timespan runPeriod_;

    /// Time the data was collected
    Timestamp dataTime_;

    /// Outputs
    DataWriter* output700Writer_;
    DataWriter* outputFDOMWriter_;
    DataWriter* outputOilWriter_;
    DataWriter* outputChlWriter_;
    DataWriter* volScat700Writer_;
    DataWriter* backScat700Writer_;

    UniversalDataWriter* fdomConcWriter_;
    UniversalDataWriter* oilConcWriter_;
    UniversalDataWriter* chlConcWriter_;

    /// Inputs
    ConfigReader* timeoutCfgReader_;
    ConfigReader* periodCfgReader_;
    ConfigReader* serialCfgReader_;
    ConfigReader* scaleFactor700CfgReader_;
    ConfigReader* darkCounts700CfgReader_;
    ConfigReader* scaleFactorFDOMCfgReader_;
    ConfigReader* darkCountsFDOMCfgReader_;
    ConfigReader* scaleFactorOilCfgReader_;
    ConfigReader* scaleFactorChlCfgReader_;
    ConfigReader* darkCountsOilCfgReader_;
    ConfigReader* darkCountsChlCfgReader_;
    ConfigReader* fdomAccuracyCfgReader_;
    ConfigReader* oilAccuracyCfgReader_;
    ConfigReader* chlAccuracyCfgReader_;

    UniversalDataReader* salinityReader_;

    /// Calibration coefficients
    float scaleFactor700_;
    int darkCounts700_;
    float scaleFactorFDOM_;
    int darkCountsFDOM_;
    float scaleFactorOil_;
    int darkCountsOil_;
    float scaleFactorChl_;
    int darkCountsChl_;


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

    // Serial number of this device
    Str serial_;

    /// Debugging outputs
    bool debug_;

    // Raw measurement for backscatter at 700nm
    int output700_;

    // Raw measurement for backscatter at FDOMnm
    int outputFDOM_;

    // Raw measurement for oil fluorescence
    int outputOil_;

    // Raw measurement for chl fluorescence
    int outputChl_;

    // Output variable
    float volScat700_;

    // Output variable
    float backScat700_;

    // Output variable
    float fdomConc_;

    // Output variable
    float oilConc_;

    // Output variable
    float chlConc_;

};
#endif /*WETLABSSEAOWL_UV_A_H*/
