#ifndef _SOUTH_DEVICE_H
#define _SOUTH_DEVICE_H

#include <list>
#include <time.h>
#include <sys/statvfs.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>


#include <klog.h>
#include <objclient.h>
#include <device.h>
#include <capability.h>

#include "south_port.h"
#include "sam.h"

class SouthDevice : public cObjectDevice, cObjectListener {
public:
    SouthDevice(
          cObjectClient *client,
          uint32_t version,
          SAM *battery
    );
    ~SouthDevice();

    void run();

    bool isOnline(){ return mOnline; }

    bool setLabel(cObjectClient *client, uint8_t input, const char *label);

protected:
    cKlog logger;
    void updatePortCount();
    // Device capabilities
    std::list<cObjectCapability*> capabilities;
    // List digital inputs ports
    std::list<DigitalInput*> diPorts;
    // List of digital output ports
    std::list<DigitalOutput*> doPorts;
    // List of analogue input ports
    std::list<AnalogueInput*> aiPorts;
    // Analogue ports
    AnalogueInput *aiPackVoltage;
    AnalogueInput *aiTemperatue;
    AnalogueInput *aiCurrent;
    AnalogueInput *aiCapacity;
    AnalogueInput *aiCycles;
    AnalogueInput *aiSOC;
    AnalogueInput *aiSOH;

    // List of analogue output ports
    std::list<AnalogueOutput*> aoPorts;

    void setOnlineStatus(cObjectDevice::eObjectStatus status);

    // RSM communication client
    cObjectClient *client;

    // Internal RSM request object handling
    void handleRequest(cObjectDevice *object);
    void handleRequest(cObjectCapability *object);
    void handleRequest(cObjectDInput *object);
    void handleRequest(cObjectDOutput *object);
    void handleRequest(cObjectAInput *object);
    void handleRequest(cObjectAOutput *object);
    void handleRequest(cObjectAnalogSample *object);

    // Internal RSM set object handling
    void handleSet(cObjectDOutput *object);
    void handleSet(cObjectAInput *object);
    void handleSet(cObjectAOutput *object);

    // Device handles request
    void handleObjectAction(cObjectList *objects);
    void handleRequest(cObjectList *objects);
    void handleSet(cObjectList *objects);
    void handleError(cObjectList *objects);
    void handleEvent(cObjectList *objects);
    void handleDelete(cObjectList *objects);
    void handleReply(cObjectList *objects);

    void updateValues();

    uint32_t sampleRate;
private:
    bool mPortsRegistered;
    int mOfflineCounter;
    uint32_t mTick;
    SAM *mSAMmonitor;
    bool mOnline;

    void sendEvent(cObjectDInput *obj);
    void sendEvent(cObjectDevice *obj);
    void addDigitalInputs();
    void addDigitalOutputs();
    void addAnalogueInputs();
    void addAnalogueOutputs();
    void addCapabilities();

};
#endif
