#ifndef NODEDRV_H
#define NODEDRV_H

#include <TString.h>

#include "log.h"

#ifdef __CINT__
typedef Byte_t   BYTE_t;
typedef UShort_t WORD_t;
typedef Short_t  WORDS_t;
typedef UInt_t   LWORD_t;
typedef Int_t    LWORDS_t;
#else
#include "gendef.h"
#endif

typedef struct timeval timeval_t;

class Network;

class NodeDrv : public Log
{
private:
    Network *fNetwork;
    BYTE_t   fId;

    TString fName;

    int fError;

protected:
    void SetError(int err) { fError = err; }
    void DelError()        { fError = 0; }

public:
    NodeDrv(BYTE_t nodeid, const char *name=NULL, MLog &out=gLog);
    virtual ~NodeDrv();

    BYTE_t      GetId() const       { return fId;   }
    const char *GetNodeName() const { return fName; }
    Network    *GetNetwork()        { return fNetwork; }

    virtual void InitDevice(Network *net);
    virtual void StopDevice() = 0;

    int  GetError() const { return fError; }
    bool HasError() const { return fError; }

    virtual void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv);
    virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx);
    virtual void HandleSDOError(LWORD_t data);

    virtual void HandlePDO1(BYTE_t *data, timeval_t *tv) {};
    virtual void HandlePDO2(BYTE_t *data, timeval_t *tv) {};
    virtual void HandlePDO3(BYTE_t *data, timeval_t *tv) {};
    virtual void HandlePDO4(BYTE_t *data, timeval_t *tv) {};

    void SendPDO1(BYTE_t data[8]);
    void SendPDO2(BYTE_t data[8]);
    void SendPDO1(BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
                  BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0);
    void SendPDO2(BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
                  BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0);

    void SendSDO(WORD_t idx, BYTE_t subidx, BYTE_t val, bool store=true);
    void SendSDO(WORD_t idx, BYTE_t subidx, WORD_t val, bool store=true);
    void SendSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, bool store=true);

    void SendSDO(WORD_t idx, BYTE_t val);
    void SendSDO(WORD_t idx, WORD_t val);
    void SendSDO(WORD_t idx, LWORD_t val=0);

    void SendNMT(BYTE_t cmd);

    void RequestSDO(WORD_t idx, BYTE_t subidx=0);

    void WaitForNextPdo1();
    void WaitForNextPdo2();
    void WaitForNextPdo3();
    void WaitForNextPdo4();

    // void WaitForSdos();
    void WaitForSdo(WORD_t idx, BYTE_t subidx=0, WORDS_t timeout=500);

    void EnableCanMsg(BYTE_t fcode);

    ClassDef(NodeDrv, 0) // base class for an object describing hardware
};

#endif
