#ifndef KTAG_H
#define KTAG_H

#include <stdint.h>
#include <klog.h>
#include "kmsgdef.h"

class KTag : public cKlog
{
public:
    enum KTagType { KT_NULL, KT_STRING, KT_UINT32, KT_UINT16, KT_UINT8, KT_BYTES, KT_FLOAT };
    virtual ~KTag();
    uint16_t getLength() const { return mDataLength + KTAG_META_LEN; }
    uint16_t getDataLength() const { return mDataLength; }
    KTagType getTagType() const { return mType; }
    uint8_t getTagID() const { return mTagID; }
    uint16_t getTag(void *buf, uint16_t len) const;
    static KTag * parseTag(void *buf, uint16_t len, void **tail);
    virtual uint16_t getMaxDataLength() { return 0; }
    KTag * getNextTag() const { return mNextTag; }
    void setNextTag(KTag *tag) { mNextTag = tag; }
protected:
    KTag(uint8_t iTagID, KTagType iType);
    void setData(void *data, uint16_t len);
    uint8_t mTagID;
    uint16_t mDataLength;
    KTagType mType;
    void *mData;
    KTag *mNextTag;
};

class KTagNull : public KTag
{
public:
    KTagNull(uint8_t iTagID);
    uint16_t getMaxDataLength() { return 0; }
};

class KTagString : public KTag
{
public:
    KTagString(uint8_t iTagID, char *str);
    uint16_t getValue(char *buf, uint16_t len) const;
    uint16_t getMaxDataLength() { return KTAG_DATA_LIMIT; }
};

class KTagUInt32 : public KTag
{
public:
    KTagUInt32(uint8_t iTagID, uint32_t val);
    KTagUInt32(uint8_t iTagID, float val);
    uint32_t getValue() const;
    float getFloatValue() const;
    virtual uint16_t getMaxDataLength() { return 4; }
};

class KTagUInt16 : public KTag
{
public:
    KTagUInt16(uint8_t iTagID, uint16_t val);
    uint16_t getValue() const;
    uint16_t getMaxDataLength() { return 2; }
};

class KTagUInt8 : public KTag
{
public:
    KTagUInt8(uint8_t iTagID, uint8_t val);
    uint8_t getValue() const;
    uint16_t getMaxDataLength() { return 1; }
};

class KTagBytes : public KTag
{
public:
    KTagBytes(uint8_t iTagID, void *bytes, uint16_t len);
    uint16_t getValue(void *buf, uint16_t len) const;
    uint16_t getMaxDataLength() { return KTAG_DATA_LIMIT; }
};

class KTagFloat : public KTagUInt32
{
public:
   KTagFloat(uint8_t iTagID,float val);
};

class KTagFactory
{
public:
    static KTag * createKTag(KTag *tag);
    static KTag * createKTag(uint8_t iTagID);
    static KTag * createKTag(uint8_t iTagID, char *str);
    static KTag * createKTag(uint8_t iTagID, uint32_t val);
    static KTag * createKTag(uint8_t iTagID, float val, bool faked=false);
    static KTag * createKTag(uint8_t iTagID, uint16_t val);
    static KTag * createKTag(uint8_t iTagID, uint8_t val);
    static KTag * createKTag(uint8_t iTagID, void *bytes, uint16_t len);
};
#endif
