/*
 * SmartHome server: Plug-in xbee
 *
 * Copyright (C) 2010 Daniel Pisi <dan.pisi@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */

/**
 * @file xbitems.h
 * @brief Digi XBee2 modules' API items
 * @author Daniel Pisi
 */

#ifndef XBITEMS_H
#define XBITEMS_H

#include <QtCore/QCoreApplication>
#include <QDataStream>
#include "xbstreamitem.h"

// -----------------------------------------------------------------------------

/**
 * \class XbFrameId
 * \brief Item storing a frame identification number
 */
class XbFrameId
{
public:
    XbFrameId(quint8 frameId = 0) { mFrameId = frameId; };

    quint8 frameId() { return mFrameId; };
    void setFrameId(quint8 frameId) { mFrameId = frameId; };

protected:
    quint8 mFrameId;
    XbStreamItem *newFrameIdItem() { return new XbUint8Item(mFrameId); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbAddr64
 * \brief 64-bit MAC address item
 */
class XbAddr64
{
public:
    XbAddr64(quint64 addr64 = 0) { mAddr64 = addr64; };

    quint64 addr64() { return mAddr64; };
    void setAddr64(quint64 addr64) { mAddr64 = addr64; };

protected:
    quint64 mAddr64;
    XbStreamItem *newAddr64Item() { return new XbUint64Item(mAddr64); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbAddr16
 * \brief 16-bit network address item
 */
class XbAddr16
{
public:
    XbAddr16(quint16 addr16 = 0xFFFE) { mAddr16 = addr16; };

    quint16 addr16() { return mAddr16; };
    void setAddr16(quint16 addr16) { mAddr16 = addr16; };

protected:
    quint16 mAddr16;
    XbStreamItem *newAddr16Item() { return new XbUint16Item(mAddr16); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbAddress
 * \brief Item storing both the 64-bit MAC and 16-bit network address
 */
class XbAddress : public XbAddr64, XbAddr16
{
public:
    XbAddress(quint64 addr64 = 0, quint16 addr16 = 0xFFFE) : XbAddr64(addr64), XbAddr16(addr16) {};

    XbStreamItem *newAddressItem() { return new XbAddressItem(mAddr64, mAddr16); };
};

// -----------------------------------------------------------------------------

/**
 * \class XbCommand
 * \brief Item encapsulating an AT command
 */
class XbCommand
{
public:
    XbCommand();

    QByteArray command();
    void setCommand(QByteArray command);
    void setCommand(QByteArray command, quint8 param);
    void setCommand(QByteArray command, XbStreamItem *param);

    XbStreamItem *cmdParam() { return mCmdParam; };

protected:
    quint8  mCommand[2];
    XbStreamItem *mCmdParam;

    void updateParamType();

    XbStreamItem *newCommandItem() { return new XbAtCommandItem(*this); };
    XbStreamItem *newCmdParamItem() { return new XbVariantItem(&mCmdParam); };

    friend class XbAtCommandItem;
};
// -----------------------------------------------------------------------------

/**
 * \class XbCmdStatus
 * \brief Item storing an AT command's status
 */
class XbCmdStatus
{
public:
    XbCmdStatus(quint8 status = 0) { mCmdStatus = status; };

    quint8 cmdStatus() { return mCmdStatus; };

protected:
    quint8 mCmdStatus;
    XbStreamItem *newCmdStatusItem() { return new XbUint8Item(mCmdStatus); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbOptions
 * \brief Item storing a packet's options
 */
class XbOptions
{
public:
    XbOptions(quint8 options = 0) { mOptions = options; };

    quint8 options() { return mOptions; };
    void setOptions(quint8 options) { mOptions = options; };

protected:
    quint8 mOptions;
    XbStreamItem *newOptionsItem() { return new XbUint8Item(mOptions); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbBcRadius
 * \brief Item specifying broadcast radius
 */
class XbBcRadius
{
public:
    XbBcRadius(quint8 radius = 0) { mBcRadius = radius; };

    quint8 broadcastRadius() { return mBcRadius; };
    void setBroadcastRadius(quint8 radius) { mBcRadius = radius; };

protected:
    quint8 mBcRadius;
    XbStreamItem *newBcRadiusItem() { return new XbUint8Item(mBcRadius); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbRfData
 * \brief Item holding transmitted data
 */
class XbRfData
{
public:
    XbRfData(QByteArray rfData = "") { mRfData = rfData; };

    QByteArray rfData() { return mRfData; };
    void setRfData(QByteArray rfData) { mRfData = rfData; };

protected:
    QByteArray mRfData;
    XbStreamItem *newRfDataItem() { return new XbByteArrayItem(mRfData); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbTxRetryCnt
 * \brief Item defining transmit retry count
 */
class XbTxRetryCnt
{
public:
    XbTxRetryCnt() { mTxRetryCnt = 0; };

    quint8 transmitRetryCount() { return mTxRetryCnt; };

protected:
    quint8 mTxRetryCnt;
    XbStreamItem *newTxRetryCntItem() { return new XbUint8Item(mTxRetryCnt); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbDeliveryStatus
 * \brief Item holding delivery status
 */
class XbDeliveryStatus
{
public:
    XbDeliveryStatus() { mDeliveryStatus = 0; };

    quint8  deliveryStatus() { return mDeliveryStatus; };
    QString deliveryStatusString();

protected:
    quint8 mDeliveryStatus;
    XbStreamItem *newDeliveryStatusItem() { return new XbUint8Item(mDeliveryStatus); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbDiscoveryStatus
 * \brief Item holding discovery status
 */
class XbDiscoveryStatus
{
public:
    XbDiscoveryStatus() { mDiscoveryStatus = 0; };

    quint8 discoveryStatus() { return mDiscoveryStatus; };

protected:
    quint8 mDiscoveryStatus;
    XbStreamItem *newDiscoveryStatusItem() { return new XbUint8Item(mDiscoveryStatus); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbSamplesCnt
 * \brief Item storing samples count
 */
class XbSamplesCnt
{
public:
    XbSamplesCnt() { mSamplesCnt = 0; };

    quint8 samplesCnt() { return mSamplesCnt; };

protected:
    quint8 mSamplesCnt;
    XbStreamItem *newSamplesCntItem() { return new XbUint8Item(mSamplesCnt); };
};
// -----------------------------------------------------------------------------

/**
 * \class XbUint8Block
 * \brief Auxiliary class for storing and streaming 8-bit unsigned values
 */
class XbUint8Block : public XbStreamItem
{
public:
    XbUint8Block(quint8 value = 0);

    quint8 value() { return mValue; };
    void setValue(quint8 value) { mValue = value; };

    virtual void wr(QDataStream &stream) { stream << mValue; };
    virtual void rd(QDataStream &stream) { stream >> mValue; };

private:
    quint8 mValue;
};
// -----------------------------------------------------------------------------

/**
 * \class XbUint16Block
 * \brief Auxiliary class for storing and streaming 16-bit unsigned values
 */
class XbUint16Block : public XbStreamItem
{
public:
    XbUint16Block(quint16 value = 0);

    quint16 value() { return mValue; };
    void setValue(quint16 value) { mValue = value; };

    virtual void wr(QDataStream &stream) { stream << mValue; };
    virtual void rd(QDataStream &stream) { stream >> mValue; };

private:
    quint16 mValue;
};
// -----------------------------------------------------------------------------

/**
 * \class XbIoSamplesBlock
 * \brief Stores a block of I/O samples
 */
class XbIoSamplesBlock : public XbStreamItemList
{
public:
    XbIoSamplesBlock();

    quint8 samplesCnt() { return mSamplesCnt; };

    quint16 digitalMask() { return mDigitalMask; };
    quint8 analogMask() { return mAnalogMask; };

    quint16 digitalSample() { return mDigitalSample; };
    quint16 analogSample(quint8 input) { return mAnalogSamples.at(input); };

protected:
    quint8  mSamplesCnt;
    quint16 mDigitalMask, mDigitalSample;
    quint8  mAnalogMask;
    QList<quint16> mAnalogSamples;

    friend class XbIoSamplesItem;
};
// -----------------------------------------------------------------------------

/**
 * \class XbIoSamples
 * \brief Item encapsulating I/O samples
 */
class XbIoSamples
{
public:
    XbIoSamples() {};

    XbIoSamplesBlock *ioSamples() { return &mIoSamplesBlock; };

protected:
    XbIoSamplesBlock mIoSamplesBlock;

    XbStreamItem *newIoSamplesItem() { return new XbIoSamplesItem(mIoSamplesBlock); };
};
// -----------------------------------------------------------------------------

#endif // XBITEMS_H
