//--------------------------------------------------------------------------
// ddp_params.h
//--------------------------------------------------------------------------

#ifndef DDP_PARAMS_H
#define DDP_PARAMS_H

#include  "ddp/ddp_port.h"
#include  "drs/drs_type.h"

#include <string>
#include <vector>

class DDP_Params
{
public:
    enum ParamType { PARAM_UNKNOWN, PARAM_INT, PARAM_TEXT, PARAM_PARAMS, PARAM_OBJECT };
    enum { PARAM_SIZE = 32768 };

protected:
    struct Param
        {
    Param() : Type(PARAM_UNKNOWN), Text(NULL), Params(NULL), Num(0) { VObject.Object = NULL;
    VObject.Size = 0; }
    Param(const Param & rhs);
    Param(const byte * name, const byte * str, ParamType type = PARAM_UNKNOWN);

    ~Param() { Clear(); }

    ParamType Type;
    std::string Name;
    struct AnyObject
    {
        void * Object;
        uint Size;
    };
    union
    {
        std::string      * Text;
        AnyObject          VObject;
        const DDP_Params * Params;
        uint               Num;
    };

    Param & operator = (const Param & rhs);
    bool operator ==(const byte * name) const;
    bool operator ==(const Param & rhs) const { return operator ==(PORT_c_str(rhs.Name)); }

    void Clear();
    ParamType FindType(const byte * type) const;
    const byte * GetTypeString(ParamType type) const;

    void SetParam(const byte * name, const byte * val, ParamType type = PARAM_UNKNOWN);
    void SetParam(const byte * buf);
    uint GetParam(std::vector<byte> & buf) const;
    uint PrintToBuf(std::vector<byte> & buf) const;
        };

protected:
    std::vector<Param *> Params;

protected:
    // helpers
    void _copy(const DDP_Params & rhs);
    const Param * get_param(uint num) const { return num < GetParamCount() ?
        Params[num] : NULL; }
    const Param * find_param(const byte * name) const;
    uint find_param_pos(const byte * name) const;

public:
    DDP_Params() {}
    DDP_Params(const DDP_Params & rhs) { _copy(rhs); }
    DDP_Params(const byte * str);
    ~DDP_Params() { Clear(); }
    
//interface:
    void SetParam(const byte * param, const byte * val, ParamType type);
    void SetParam(const byte * param, const byte * val) { SetParam(param, val, PARAM_TEXT); }
    void SetParam(const byte * param, uint val);
    void SetParam(const byte * param, const void * obj, uint size);
    void SetParam(const byte * param, const DDP_Params * params);

    uint GetParamCount() const { return Params.size(); }
    void Clear();

    // assignment:
    DDP_Params & operator =(const DDP_Params & rhs) { _copy(rhs);
        return *this; }

    // param access:
    const byte * GetParamName(uint num) const { const Param * p = get_param(num);
        return p ? PORT_c_str(p->Name) : NULL; }
    ParamType GetParamType(uint num) const { const Param * p = get_param(num);
        return p ? p->Type : PARAM_UNKNOWN; }

    // value access:
    uint GetInt(uint num) const;
    uint GetInt(const byte * param) const { uint pos = find_param_pos(param);
        return GetInt(pos); }

	#ifdef GetObject
	#undef GetObject
	#endif

    void * GetObject(uint num, uint * sz = NULL) const;
    void * GetObject(const byte * param, uint * sz = NULL) const { uint pos = find_param_pos(param);
        return GetObject(pos, sz); }

    DDP_Params GetParams(uint num) const;
    DDP_Params GetParams(const byte * param) const { uint pos = find_param_pos(param);
        return GetParams(pos); }

    std::string GetText(uint num) const;
    std::string GetText(const byte * param) const { uint pos = find_param_pos(param);
        return GetText(pos); }

    uint PrintToBuf(std::vector<byte> & buf) const;    
};

#endif // DDP_PARAMS_H