#ifndef SOUTH_PORT_H
#define SOUTH_PORT_H

#include <stdio.h>
#include <stdint.h>

#include <klog/klog.h>
#include <objclient.h>
#include <object.h>
#include <dinput.h>
#include <doutput.h>
#include <ainput.h>
#include <aoutput.h>
#include <asample.h>
#include <capability.h>


/* == Digital Input Port == */
class DigitalInput : public cObjectDInput {
public:
    DigitalInput(uint32_t serial, uint32_t portNo, const char *label);
    ~DigitalInput();

    void setInput(cObject::eObjectIOState state, cObjectClient &client);
protected:
    cKlog logger;
    void sendEvent(cObjectClient &client);
};

/* == Digital Output Port == */
class DigitalOutput : public cObjectDOutput {
public:
    DigitalOutput(uint32_t serial, uint32_t portNo, const char *label);
    ~DigitalOutput();
protected:
    cKlog logger;
private:

};

typedef struct _AnalogueSample {
    uint8_t sequence;
    float value;
} AnalogueSample;

#define ANALOGUE_SAMPLE_SIZE 32

/* == Analogue Input Port == */
class AnalogueInput : public cObjectAInput {
public:
    AnalogueInput(uint32_t serial, uint32_t portNo, const char *label, const char *unit, double gain, double offset, int sampleRate);
    ~AnalogueInput();
    void sample(float value, cObjectClient &client);
    cObjectAnalogSample* hasSample(uint8_t sequence);
protected:
    cKlog logger;
    void sendSampleEvent(cObjectClient &client, uint8_t sequence);
    cObjectAnalogSample* createSample(uint8_t seq);
private:
    uint32_t samplingRateSec; // Rate in seconds
    uint32_t rateCounter;
    // Circular samples
    uint8_t currentSequence;
    uint8_t currentIndex;
    AnalogueSample samples[ANALOGUE_SAMPLE_SIZE] = {};
};

class CompositeAnalogInput : public AnalogueInput
{
public:
	enum eMathOp {
		OP_DIV,
		OP_MUL
	};
	CompositeAnalogInput(uint32_t serial, uint32_t portNo, const char *label, const char *unit, AnalogueInput * arg1,AnalogueInput * arg2, eMathOp op);
	void update(cObjectClient &client);
private:
	AnalogueInput * mArg1;
	AnalogueInput * mArg2;
	eMathOp mMathOp;
};

/* == Analogue Output Port == */
class AnalogueOutput: public cObjectAOutput {
protected:
   cKlog logger;
public:
    AnalogueOutput(uint32_t serial, uint32_t portNo, const char *label, const char *unit, double gain, double offset, int sampleRate);
    ~AnalogueOutput();
};

#endif // SOUTH_PORT_H
