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

#ifndef BATT_OCEAN_SERVER_H
#define BATT_OCEAN_SERVER_H

#include "Batt_Ocean_ServerIF.h"

#define NUM_BATTSA Batt_Ocean_ServerIF::NUM_BATTSA
#define NUM_BATTSB Batt_Ocean_ServerIF::NUM_BATTSB

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

class UniversalDataWriter;

/**
 *  Provides software interface to the Ocean Server Battery Boards.
 *
 *  \ingroup modules_sensor
 */
class Batt_Ocean_Server : public SyncSensorComponent
{
public:

    Batt_Ocean_Server( const Module* module );

    virtual ~Batt_Ocean_Server();

    void initialize();

    // The actual "payload" of the component
    void run();

    void uninitialize();


private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    Batt_Ocean_Server( const Batt_Ocean_Server& old ); // disallow copy constructor

    Timespan battTimeout_;
    Timestamp startTimeA_;
    Timestamp startTimeB_;

    // The status returned from the battery controller
    typedef enum
    {
        // ALARM BITS
        OVER_CHARGED_ALARM = 0x8000,
        TERMINATE_CHARGE_ALARM = 0x4000,
        OVER_TEMP_ALARM = 0x1000,
        TERMINATE_DISCHARGE_ALARM = 0x0800,
        REMAINING_CAPACITY_ALARM = 0x0200,
        REMAINING_TIME_ALARM = 0x0100,
        // STATUS BITS
        INITIALIZED = 0x0080,
        DISCHARGING = 0x0040,
        FULLY_CHARGED = 0x0020,
        FULLY_DISCHARGED = 0x0010
    } SMBStatus;

    // Boolean flag
    bool initialized_;

    // True if we have alerted user that we are using Simulator instead of hardware.
    bool usingSimWarned_;

    // Stores the current response from the battery server
    char deviceResponseA_[1023];
    char deviceResponseB_[1023];

    // Holds the communications device
    UartStream uartA_;
    UartStream uartB_;

    // Store the totals
    float totalCapacityA_;
    float totalVoltageA_;
    float totalCapacityB_;
    float totalVoltageB_;

    bool readEEPROM( unsigned short &value, const unsigned char address );

    bool readTemperature( float &temperature );

    bool readTransducers( float &roll, float &pitch, float &magHeading,
                          float &rollRate, float &pitchRate, float &yawRate );

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

    // Checks to see that our current capacity is above the threshold
    void checkBatt( const float capacity, const float voltage );

    /// Data structure looks as follows:
    //
    //Battery:| (01)   (02)   (03)   (04)   (05)   (06)   (07)   (08)
    //Status: | 00C0   00C0   00C0   00C0   00C0   00C0   00C0   00C0
    //        | . .    . .    . .    . .    . .    . .    . .    . .
    //
    //Voltage |16.349 16.363 16.396 16.375 16.442 16.375 16.464 16.404
    //Current |  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00
    //
    //Temp C  |  21.6   22.5   23.0   23.1   24.8   24.0   23.3   22.7
    //Charge% |    91     91     78     78     88     91     79     79
    //Cap Ah  |  5.90   5.86   4.68   4.67   5.88   5.77   4.70   4.70
    //
    // Current: 0.000 A,  Power: 0.0 W
    // Voltage: 16.39 V -> 16.39 V
    // Avg Charge: 84%, Cycles: 2

    struct BattPack
    {
        // Constructor
        BattPack();

        // The battery status
        int status_;
        // And its writer
        DataWriter *battStatusWriter_;

        // The battery voltage
        float voltage_;
        DataWriter *battVoltageWriter_;

        // The battery current
        float current_;
        DataWriter *battCurrentWriter_;

        // The battery temp
        float temp_;
        DataWriter *battTempWriter_;

        // The battery charge
        float charge_;

        // The battery capacity
        float capacity_;
        DataWriter *battCapacityWriter_;
    };

    // Array to store the battery packs and their associated writers
    BattPack battPacks_[NUM_BATTSA + NUM_BATTSB];

    UniversalDataWriter* batteryChargeWriter_;
    UniversalDataWriter* batteryVoltageWriter_;
    UniversalDataWriter* batteryDischargingWriter_;
    UniversalDataWriter* batteryFullyChargedWriter_;

    /// Configuration Readers
    ConfigReader* batteryCapacityThresholdCfgReader_; // Amount of charge left at which we return to the surface
    ConfigReader* batteryVoltageThresholdCfgReader_;  // Amount of voltage left at which we return to the surface

    bool readDataA();
    bool readDataB();

    // indicates whether things are ok to run
    bool ok_;

    float batteryCapacityThreshold_;
    float batteryVoltageThreshold_;

    // True if we have detected an under threshold value for capacity or voltage
    bool capacityFailed_;
    bool voltageFailed_;

};
#endif /*BATT_OCEAN_SERVER_H*/
