#ifndef ADS_DATA_H_
#define ADS_DATA_H_

#include "ads_manager.h"

#include <QObject>
#include <QAction>

#include "ads_fastslots.h"

class AdsLogicDataDelegate
{
public:
  virtual void set(Ads1553MsgQ&, int w, long value, unsigned int pos, unsigned int mask) const =0;
  virtual long get(Ads1553MsgQ&, int w, unsigned int pos, unsigned int mask) const =0;

  virtual long get(const unsigned short* const d, int w, unsigned int pos, unsigned int mask) const =0;

  virtual unsigned int wordSelector(int w) const =0;

  virtual long min() const =0;
  virtual long max() const =0;
};

extern AdsLogicDataDelegate& AdsLogicDataDelegateUInt16;
extern AdsLogicDataDelegate& AdsLogicDataDelegateInt16;
extern AdsLogicDataDelegate& AdsLogicDataDelegateInt32;

class AdsLogicData: public QObject
{
  Q_OBJECT

public:
  AdsLogicData( const char* const name=0, AdsLogicDataDelegate* delegate=&AdsLogicDataDelegateUInt16);

  void setDataName(const char* const name);
  void setManipulator(AdsLogicDataDelegate& m);
  void setFormat(unsigned int pos, unsigned int mask);
  void setRange(int min, int max);
  void setLsb(double lsb);
  double getLsb() const { return lsb;}

  void attachToMsg(Ads1553MsgQ* const msg, int w);

  void setValidity(AdsLogicData*) {}
  void setScaler(AdsLogicData*) {}

  bool isReadOnly() const;
  bool isValid() const { return true;}
  bool isOutOfRange() const;

  virtual bool toBool() const;
  double toDouble() const;

  double cvFromExtern(const unsigned short* const m) const;

  int getValue() const { return value_;}
  Ads1553MsgQ* getMsg() const { return pMsg;}

  AdsLogicDataDelegate& getManipulator() const;

signals:
  void sigUpdated();

  void rawUpdated(int);

public slots:
  virtual void setFromRaw(int);
  virtual void setFromUser(int);
  virtual void setFromUser(double);

protected:
  AdsLogicDataDelegate* manipulator;

  int value_;
  mutable double cached_value;

  Ads1553MsgQ* pMsg;

  int wPos;
  int rMin;
  int rMax;
  unsigned int rPos;
  unsigned int rMask;
  double lsb;

  unsigned int busMask;

  AdsLogicData* validity;
  AdsLogicData* scaler;

  //static void onMsgReceived_callback(Ads1553MsgQ*, void* arg);
  ADS_SLOT(onMsgReceived_callback, (Ads1553MsgQ*));
  virtual void onMsgReceived(Ads1553MsgQ*);
};

class AdsDataAction: public QObject
{
  Q_OBJECT

public:
  AdsDataAction(AdsLogicData* datum=0, const char* const name=0);

  void attachTo(AdsLogicData*);

  virtual void execute(bool active=true);

public slots:
  void onQAction();

protected:
  AdsLogicData* d;
};

class AdsDataActionSet: public AdsDataAction
{
public:
  AdsDataActionSet(AdsLogicData* datum=0);

  void setActionValue(int value);

  virtual void execute(bool active=true);
protected:
  int set_value;
};

class AdsDataActionSet2: public AdsDataAction
{
public:
  AdsDataActionSet2(AdsLogicData* datum=0, AdsLogicData* d2=0);

  void attachTo(AdsLogicData* d1, AdsLogicData* d2);

  void setActionValue(int value1, int value2);

  virtual void execute(bool active=true);
protected:
  int set_value1;
  int set_value2;

  AdsLogicData* d2;
};

class AdsDataActionSetReset: public AdsDataActionSet
{
public:
  AdsDataActionSetReset(AdsLogicData* datum=0);

  void setActionValue(int set_value, int reset_value, int delay);

  virtual void execute(bool active=true);
protected:
  int reset_value;
  int reset_delay;

  static void reset_action(void* arg);
  static void preset_action(void* arg);
};

class AdsDataActionCycle: public AdsDataActionSet
{
public:
  AdsDataActionCycle(AdsLogicData* datum=0);

  void setActionValue(int min, int max);

  virtual void execute(bool active=true);
protected:
  int v_max;

};

class AdsDataActionSetAndCycle: public AdsDataActionCycle
{
public:
  AdsDataActionSetAndCycle(AdsLogicData* master_datum=0, AdsLogicData* datum=0);

  void attachTo(AdsLogicData* d1, AdsLogicData* d2);
  void setActionValue(int master_value, int min, int max);

  virtual void execute(bool active=true);
protected:
  AdsLogicData* m_datum;
  int m_value;
};

/*
class AdsDataActionMap: public QObject
{
  Q_OBJECT

public:
  AdsDataActionMap(AdsDataAction* dataAct, QAction* qact);

public slots:
  void execute();

private:
   AdsDataAction* dAct;
   QAction* qAct;
};
*/

class AdsDataManager
{
public:
  static AdsLogicData* findLogicData(const QString& name);
  static AdsDataAction* findDataAction(const QString& name);

  static int logicDataCount();
  static AdsLogicData* getLogicData(int pos);

  static int dataActionCount();
  static AdsDataAction* getDataAction(int pos);

  static QString makeUnknownName();
};


#endif /*ADS_DATA_H_*/
