/** \file
 *
 *  Contains the BackseatComponent class declaration.
 *
 *  BackseatComponent.h should only be included by BackseatComponent.cpp
 *  Other classes should include BackseatComponentIF.h
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 *  This class simply provides power and a data writer to
 *  allowing a mission to request it
 */

#ifndef BACKSEATCOMPONENT_H_
#define BACKSEATCOMPONENT_H_

#include "component/AsyncComponent.h"
#include "io/LoadControl.h"
#include "logger/Logger.h"
#include "units/UnitRegistry.h"
#include "supervisor/LcmSlateBridge.h"
#include "supervisor/LcmSlateRequest.h"
#include "supervisor/LcmSyslogBridge.h"

// For LCM messaging
#include <vector>
#include "LcmMessageReader.h"
#include "LcmMessageWriter.h"
#include "TethysLcmTypes/LrauvLcmMessage.hpp"


class UniversalDataWriter;


class BackseatWriter
{
public:
    BackseatWriter( const Str& channelName );

    ~BackseatWriter() {}

    bool writeStr( const Str& varName, const Str& str );

    bool writeStr( const Str& varName, const char* str );

    bool writeBool( const Str& varName, bool val );

    bool publish( long long epoch_millisec );

    void setChannel( const Str& channelName )
    {
        channel_ = channelName;
    }

    const Str& channel( void )
    {
        return channel_;
    }

protected:

    Str channel_;
    lrauv_lcm_tools::LcmMessageWriter<> msg_;

};

/**
 *
 *  Load control port interface to power on/off a back-seat-driver (BSD) secondary processing unit.
 *  The BackseatComponent also provides a software interface to the BSD via LCM messaging.
 *
 */
class BackseatComponent : public AsyncComponent
{
public:

    BackseatComponent( const Module* module );

    virtual ~BackseatComponent();

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

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

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

    /// LCM channel name difinition
    static const Str heartbeatLcmChannel_;
    static const Str dataRequestLcmChannel_;
    static const Str syslogLcmChannel_;
    static const Str commandLcmChannel_;

    //*------------------- vehicle parameters --------------------------*/

    LcmSlateRequest slateRequest_;

    LcmSyslogBridge syslogBridge_;

    LcmListener heartbeatListener_;

    BackseatWriter cmdWriter_;

    /// Subscribes handler to LCM channel
    void subscribe( void );

    /// Subscribes handler from LCM channel
    void unsubscribe( void );

    /// Publishes a command to the BSD on LCM channel
    bool publishCommand( Str& cmd );

    /// Sends a shutdown request to the BSD on LCM channel
    void requestShutdown( void );

    // Slate outputs
    DataWriter* powerBackseatWriter_;
    DataWriter* msgHandleWriter_;

    // Slate Inputs
    // DataReader* commandValueDataReader_;
    DataReader* msgHandleReader_;
    DataReader* power24vConverterDataReader_;

    // Configuration inputs
    ConfigReader* listenLcmChannelNameCfgReader_;
    ConfigReader* lcmListenerTimeoutCfgReader_;
    ConfigReader* shutdownCmdCfgReader_;
    ConfigReader* verbosityCfgReader_;
    ConfigReader* alwaysOnCfgReader_;
    ConfigReader* needs24vCfgReader_;

    // Power for the device
    LoadControl loadControl_;

    // Optional second instance of load controller
    LoadControl loadControl2_;
    bool hasLoadControl2_;

    // Command to power down the BSD
    Str shutdownCmd_;

    // Component timeouts
    Timespan vitalsTimeout_;
    Timespan poTimeout_;
    Timespan listenerTimeoutSec_;

    // Initializes vehicle config variables
    bool readConfig( void );

    // Queries the LCBs for status
    void logVoltageAndCurrent( void );

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

    // Time started
    Timestamp startTime_;

    // Indicates whether a shutdown request has been issued
    bool shutdownRequested_;

    // Indicates whether the BSC should remain on at all times
    bool keepOn_;

    // Indicates whether the BSC requires 24v power
    bool needs24v_;

    bool isMissionCritical_;

    int verbosity_;

    // Debugging outputs
    bool debug_;

};
#endif /*BACKSEATCOMPONENT_H_*/
