#ifndef LIP_OPCUA_TREE_ITEM_REF_H
#define LIP_OPCUA_TREE_ITEM_REF_H

#include "lip/lip_defs.h"

struct st_lip_opcua_tree_item;

typedef enum {
    LIP_OPCUA_TREE_ITEM_REFFLAG_INVERSE     = 1 << 0,
} t_lip_opcua_tree_item_ref_descr_flags;

typedef enum {
    LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_NULL            = 0, /* пустая запись */
    LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_SINGLE          = 1, /* Запись описывает одну ссылку (поле target_node) */
    LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_MULTIPLE        = 2, /* Запись описывает несколько ссылок одного типа */
    LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_REF_DESCR_LIST  = 3, /* запись включает указатель на следующий список с описанием ссылок */
} t_lip_opcua_tree_item_ref_descr_type;

typedef struct st_lip_opcua_tree_item_ref_descr {
    uint8_t rec_type;
    uint8_t inverse;
    uint8_t last;
    uint8_t cnt;
    const struct st_lip_opcua_tree_item *ref_type;
    union {
        const struct st_lip_opcua_tree_item *target_node;
        const struct st_lip_opcua_tree_item **target_nodes;
        const struct st_lip_opcua_tree_item_ref_descr *ref_descr_list;
    };
} t_lip_opcua_tree_item_ref_descr;

typedef struct st_lip_opcua_tree_item_ref {
    uint8_t inverse;
    const struct st_lip_opcua_tree_item *ref_type;
    const struct st_lip_opcua_tree_item *target_node;
} t_lip_opcua_tree_item_ref;


#define LIP_OPCUA_TREE_REF_DECL_NULL()   {.last = true, .rec_type = LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_NULL}
#define LIP_OPCUA_TREE_REF_IS_NULL(ref)  ((ref).rec_type == LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_NULL)
#define LIP_OPCUA_TREE_REF_IS_LAST(ref)  ((ref).last)


#define LIP_OPCUA_TREE_REF_DECL_NEXT                            .last = false},
#define LIP_OPCUA_TREE_REF_DECL_END                              .last = true}
#define LIP_OPCUA_TREE_REF_DECL_START_SINGLE(rtype, tnode, inv)  {.rec_type = LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_SINGLE, .inverse = (inv), .ref_type = &rtype, .target_node = &tnode,
#define LIP_OPCUA_TREE_REF_DECL_SINGLE_FWD(rtype, tnode) LIP_OPCUA_TREE_REF_DECL_START_SINGLE(rtype, tnode, false)
#define LIP_OPCUA_TREE_REF_DECL_SINGLE_INV(rtype, tnode) LIP_OPCUA_TREE_REF_DECL_START_SINGLE(rtype, tnode, true)
#define LIP_OPCUA_TREE_REF_DECL_START_MULTI(rtype, targets, inv) {.rec_type = LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_MULTIPLE, \
            .inverse = (inv), .ref_type = &rtype, .cnt = sizeof(targets)/sizeof((targets)[0]), .target_nodes = (targets),
#define LIP_OPCUA_TREE_REF_DECL_MULTI_FWD(rtype, targets) LIP_OPCUA_TREE_REF_DECL_START_MULTI(rtype, targets, false)
#define LIP_OPCUA_TREE_REF_DECL_MULTI_INV(rtype, targets) LIP_OPCUA_TREE_REF_DECL_START_MULTI(rtype, targets, true)

#define LIP_OPCUA_TREE_REF_DECL_NEXT_DESCR_LIST(list)    {.rec_type = LIP_OPCUA_TREE_ITEM_REFF_DESCR_TYPE_REF_DESCR_LIST, .inverse = false, .ref_type = NULL, .ref_descr_list = &(list),

#endif // LIP_OPCUA_TREE_ITEM_REF_H
