#ifndef LIP_OPCUA_NODEID_H
#define LIP_OPCUA_NODEID_H

#include "lip_opcua_string.h"
#include "lip_opcua_guid.h"

typedef enum {
    LIP_OPCUA_NODEID_TYPE_INVALID       = 0,
    LIP_OPCUA_NODEID_TYPE_INT           = 1,
    LIP_OPCUA_NODEID_TYPE_STRING        = 2,
    LIP_OPCUA_NODEID_TYPE_GUID          = 3,
    LIP_OPCUA_NODEID_TYPE_BYTESTRING    = 4,
} t_lip_opcua_nodeid_type;

typedef struct st_lip_opcua_nodeid {
    uint8_t type;
    uint8_t res;
    uint16_t ns_idx;
    union {
        uint32_t intval;
        t_lip_opcua_string_ptr str;
        const uint8_t *guid;
    };
} t_lip_opcua_nodeid;


static LINLINE bool lip_opcua_nodeid_check_is_stdns_int(const t_lip_opcua_nodeid *nodeid) {
    return (nodeid->type == LIP_OPCUA_NODEID_TYPE_INT) && (nodeid->ns_idx == 0);
}

static LINLINE bool lip_opcua_nodeid_is_eq(const t_lip_opcua_nodeid *n1, const t_lip_opcua_nodeid *n2) {
    bool eq = (n1->type == n2->type) && (n1->ns_idx == n2->ns_idx);
    if (eq) {
        if (n1->type == LIP_OPCUA_NODEID_TYPE_INT) {
            eq = n1->intval == n2->intval;
        } else if ((n1->type == LIP_OPCUA_NODEID_TYPE_STRING) || (n1->type == LIP_OPCUA_NODEID_TYPE_BYTESTRING)) {
            eq = lip_opcua_string_is_eq(&n1->str, &n2->str);
        } else if (n1->type == LIP_OPCUA_NODEID_TYPE_GUID) {
            eq = memcmp(n1->guid, n2->guid, LIP_OPCUA_GUID_SIZE) == -1;
        }
    }

    return eq;
}


#define LIP_OPCUA_NODEID_STDNS_INT(nodeid_val) {.ns_idx=LIP_OPCUA_NAMESPACE_IDX_OPCUA,.type=LIP_OPCUA_NODEID_TYPE_INT,.intval=(nodeid_val)}
#define LIP_OPCUA_NODEID_IS_EQ_STDNS_INT(nodeid, nodeid_val) (((nodeid).ns_idx == LIP_OPCUA_NAMESPACE_IDX_OPCUA) && ((nodeid).type == LIP_OPCUA_NODEID_TYPE_INT) && ((nodeid).intval == (nodeid_val)))



#endif // LIP_OPCUA_NODEID_H
