#ifndef KOURIERERR_H
#define KOURIERERR_H

#include "klist.h"
#include "kerror.h"

enum KourierErrorCode {
    KOURIER_ERROR_NONE,
    KOURIER_ERROR_UNKNOWN_MSGID,
    KOURIER_ERROR_UNKNOWN_TAGID,
    KOURIER_ERROR_MISSING_TAG,
    KOURIER_ERROR_TAG_TYPE,
    KOURIER_ERROR_BUFFER_SIZE,
    KOURIER_ERROR_MSG_PROCESS,
    KOURIER_ERROR_MSG_PARSE,
    KOURIER_ERROR_TAG_PROCESS,
    KOURIER_ERROR_TAG_PARSE,
    KOURIER_ERROR_NULL_POINTER,
    KOURIER_ERROR_TAG_COUNT
};

class KourierError : public KError
{
public:
    KourierError(KourierErrorCode iCode, const void *iData, uint16_t iDataLen) :
            KError((uint16_t)iCode, iData, iDataLen),
            mCode(iCode) {}
    KourierErrorCode getCode() { return mCode; }
protected:
    KourierErrorCode mCode;
};

class KErrorMsgID : public KourierError
{
public:
    KErrorMsgID(uint8_t id) :
            KourierError(KOURIER_ERROR_UNKNOWN_MSGID, (void *)&id, sizeof(id)) {}
    uint8_t getID() { return *((uint8_t *)mErrorData); }
};

class KErrorTagID : public KourierError
{
public:
    KErrorTagID(uint8_t id) :
            KourierError(KOURIER_ERROR_UNKNOWN_TAGID, (void *)&id, sizeof(id)) {}
    uint8_t getID() { return *((uint8_t *)mErrorData); }
};

class KErrorMissingTag : public KourierError
{
public:
    KErrorMissingTag(uint8_t id) :
            KourierError(KOURIER_ERROR_MISSING_TAG, (void *)&id, sizeof(id)) {}
    uint8_t getID() { return *((uint8_t *)mErrorData); }
};

class KErrorTagType : public KourierError
{
public:
    KErrorTagType(uint8_t id) :
            KourierError(KOURIER_ERROR_TAG_TYPE, (void *)&id, sizeof(id)) {}
    uint8_t getID() { return *((uint8_t *)mErrorData); }
};

class KErrorBufferSize : public KourierError
{
public:
    KErrorBufferSize(uint16_t len) :
            KourierError(KOURIER_ERROR_BUFFER_SIZE, (void *)&len, sizeof(len)) {}
    uint16_t getLen() { return *((uint16_t *)mErrorData); }
};

class KErrorMsgProcess : public KourierError
{
public:
    KErrorMsgProcess() :
            KourierError(KOURIER_ERROR_MSG_PROCESS, 0, 0) {}
};

class KErrorMsgParse : public KourierError
{
public:
    KErrorMsgParse() :
            KourierError(KOURIER_ERROR_MSG_PARSE, 0, 0) {}
};

class KErrorTagProcess : public KourierError
{
public:
    KErrorTagProcess() :
            KourierError(KOURIER_ERROR_TAG_PROCESS, 0, 0) {}
};

class KErrorTagParse : public KourierError
{
public:
    KErrorTagParse() :
            KourierError(KOURIER_ERROR_TAG_PARSE, 0, 0) {}
};

class KErrorNullPointer : public KourierError
{
public:
    KErrorNullPointer() :
            KourierError(KOURIER_ERROR_NULL_POINTER, 0, 0) {}
};

class KErrorTagCount : public KourierError
{
public:
    KErrorTagCount(int16_t diff) :
            KourierError(KOURIER_ERROR_TAG_COUNT, &diff, sizeof(diff)) {}
    int16_t getDiff() { return *((int16_t *)mErrorData); } 
};

class KourierErrors : public KList
{
public:
    KourierErrors() {}
    ~KourierErrors()
    {
        KourierError *e;
        do
        {
            e = pullError();
            if(e)
                delete e;
        } while (e != 0);
    }
    void addError(KourierError *error) { add((void *)error); }
    KourierError * pullError() { return (KourierError *)pull(); }
    bool hasErrors() { return !empty(); }
};

#endif
