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

#ifndef DEPTHKELLER33X_H_
#define DEPTHKELLER33X_H_

#include "component/SyncComponent.h"
#include "io/LoadControl.h"
#include "io/UartStream.h"
#include "logger/Logger.h"

class UniversalDataReader;
class UniversalDataWriter;

/**
 *  Provides software interface to the Keller depth sensor
 *  Can also use SimSlate to provide simulated depth values when
 *  they are available.
 *
 *  DepthKeller33X.h should only be included by DepthKeller33X.cpp
 *  Other classes should include DepthKeller33XIF.h
 *
 *  \ingroup modules_sensor
 */
class DepthKeller33X: public SyncSensorComponent
{
public:
    DepthKeller33X( const Module* module );

    virtual ~DepthKeller33X();

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

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

    /// Instance of load controller
    LoadControl loadControl_;

    /// Holds the communications device
    UartStream uart_;

    static const unsigned int MAX_DEVICE_RESPONSE = 128;

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

    /// Max number of packets queued up in the buffer
    static const unsigned int MAX_DEVICE_MSG_QUEUE_SIZE;

    /// Expected number of bytes read in valid message (Paro serial format)
    static const unsigned int MIN_DEVICE_RESPONSE;

    /// Reads in component configuration
    bool readConfig();

    /// Read in and QC latitude
    void readLatitude();

    /// Read and QC latitude
    bool readPressure();

    /// Reads and processes the latest pressure measurement
    bool processPressure();

    /// Computes depth in meters from pressure in pascals and latitude in radians
    bool processDepth();

    /// Logs voltage and current and check for any faults
    void logVoltageAndCurrent();

    /// Universal Slate readers
    UniversalDataReader* latitudeReader_;

    /// Universal Slate writers
    UniversalDataWriter* depthWriter_;
    UniversalDataWriter* pressureWriter_;

    /// Slate configuration readers
    ConfigReader* offsetCfgReader_;
    ConfigReader* maxPressBoundCfgReader_;
    ConfigReader* minPressBoundCfgReader_;

    /// Holds the power-on timeout
    Timespan poTimeout_;

    /// Holds the component's data timeout
    Timespan timeout_;

    /// Hold the component's start and data times
    Timestamp startTime_, dataTimestamp_;

    /// Holds the pressure offset config setting
    float pressureOffset_;

    /// Holds the max pressure bound config setting
    float maxPressBound_;

    /// Holds the min pressure bound config setting
    float minPressBound_;

    /// Holds the latest pressure measurement
    double pressure_;

    /// Holds the latest latitude reading
    double latitude_;

    /// Holds the latest depth measurement
    double depth_;

    /// Enables debug syslog output
    bool debug_;
};

#endif /* DEPTHKELLERX33_H_ */
