/** \file
 *
 *  Contains the BPC1_BattBank class declaration.
 *
 *  Copyright (c) 2014 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */


#ifndef BPC1_BATTBANK_H
#define BPC1_BATTBANK_H

#include <vector>
#include "data/DataElement.h"
#include "io/UartStream.h"
#include "logger/Logger.h"
#include "BPC1_BattStick.h"
#include "BPC1IF.h"

#define IPBS_MENU_MSG "H -" // Chars to identify IBPS menu response


class BattBank
{
public:
    // Constructor
    BattBank( const ConfigURI& uartCfg, const ConfigURI& baudCfg, Logger& logger, size_t bufferSize,
              const double timeoutSec, const int numBattSticks, const int numReserveSticks,
              const int stickOffset, Str bankName );

    ~BattBank();

    // Runs the internal battery bank state machine
    bool runBank( void );

    void setVoltagesNull( void );

    // Indicates the bank has encountred a data error
    bool hasDataError( void )
    {
        return dataError_;
    };

    void setWritersInvalid( bool invalid );

    // Reset the internal battery bank state
    void initializeBankState( void );

    // Enables battary bank UART
    bool enableUART( void );

    // Disables battary bank UART
    void closeUART( void );

    // Flushes battary bank UART
    void flushUART( void );

    // Sends the break (space) character to the Intelligent Battery and Power System
    void sendIBPSBreak( void );

    // Sends the X character to the Intelligent Battery and Power System
    void requestHexData( void );

    // Returns true if port is initialized to the banner menu offering hex output
    bool menuInitialized( void );

    int NumBattSticks( void )
    {
        return numBattSticks_;
    }

    int NumReserveSticks( void )
    {
        return numReserveSticks_;
    }

    int StickOffset( void )
    {
        return stickOffset_;
    }

    Str Name( void )
    {
        return name_;
    }

    BattStick* getStick( int i )
    {
        return &battSticks_[i];
    }

    bool isCharging()
    {
        return charging_;
    }

private:

    // Holds the communication device
    UartStream uart_;

    // Log instance
    Logger logger_;

    // Batt bank attributes
    int numBattSticks_, numReserveSticks_, stickOffset_;

    // Stores the battery bank's name
    Str name_;

    // Stores the battery stick objects (including their associated writers)
    std::vector<BattStick> battSticks_;

    // BattBank constants
    static const unsigned short MAX_STICKS;        // There can only be up to 8 sticks connected.
    static const unsigned short MIN_STICKS;        // Min 7 sticks connected.
    static const unsigned int HEX_REQUEST;         // bytes.
    static const unsigned int MESSAGE_OFFSET;      // bytes. Length of system and controller data
    static const unsigned int SHORT_IBPS_MENU;     // bytes.
    static const unsigned int LONG_IBPS_MENU;      // bytes.
    static const unsigned int SMBUS_STICK_MSG_LEN; // bytes. Includes the $B1n and checksum that IBPS adds

    // Indicates the bank has encountred a data error
    bool dataError_;

    typedef enum
    {
        INITIALIZE,   // IBPS menu initilasation
        REQUEST_DATA, // Hex data request
        WAIT,         // Wait for short message to clear and issue IBPS break
        VALIDATE,     // Confirm parsable data format
        PARSE,        // Parse message and write
    } RunSequance;

    RunSequance bankRunState_;

    // Holds size (bytes) of parsable data
    unsigned int msgSize_;

    // Holds the expected device response byte size
    static const unsigned int MAX_DEVICE_RESPONSE_SIZE = 2310;

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

    bool debug_;

    // True if any of the sticks in the most recent query cycle think they're
    // not discharging
    bool charging_;

    bool getValidBytes( unsigned int& numBytes );

    bool parseWriteData( void );

};


#endif /* BPC1_BATTBANK_H */
