#ifndef __IFAA_TLV_PARSER_H__
#define __IFAA_TLV_PARSER_H__

#include "ifaa_tlv_common.h"
#include "ifaa_ta_common.h"

#define TLSIZE (2 * sizeof(uint16_t))
#define GET_NODE_DATA_PTR(ptr) (ptr + TLSIZE)
#define GET_NODE_DATA_SIZE(ptr) (read16((ptr) + sizeof(uint16_t)))
#define GET_NODE_SIZE(ptr) (TLSIZE + GET_NODE_DATA_SIZE(ptr))

typedef enum { REG_REQUEST, AUTH_REQUEST, DEREG_REQUEST } request_type;

typedef struct tlv_node {
    uint16_t tag;
    uint16_t length;
    uint8_t* value;
    struct tlv_node* child;
    struct tlv_node* sibling;
} tlv_node_t;

#define TLV_ADD_CHILD(p, c)               \
    {                                     \
        tlv_node_t* old = p.child;        \
        p.child = &c;                     \
        c.sibling = old;                  \
    }

#define CREATE_TLV_NODE(n, t, l, v)       \
    tlv_node_t n = {0};                   \
    n.tag = (t);                          \
    n.length = (uint16_t)(l);             \
    n.value = (v);                        \
   
#define SET_TLV_VALUE(n,t,l,v)          \
    {                                   \
        n.tag = (t);                    \
        n.length = (uint16_t)(l);       \
        n.value = (v);                  \
    }

EXTERNC tlv_node_t* free_tlv_tree(tlv_node_t* node);

EXTERNC tlv_node_t* find_node_by_tag(tlv_node_t* node, tag_t tag);

typedef IFAA_Result (*IFAA_Validator)(tlv_node_t *root_node);

EXTERNC IFAA_Result parse_request(vlb_t* req, request_type type,
                                  tlv_node_t** node, IFAA_Validator validator);


typedef IFAA_Result (*IFAA_RegRespSigner)(const uint8_t *source, uint32_t src_len,
                                          uint8_t *sig, uint32_t *sig_len);



EXTERNC IFAA_Result generate_reg_response(const vlb_t *user_token,
                                  const vlb_t *pub_alg_encode, const vlb_t *pubkey,
                                  const vlb_t *key_type, const vlb_t *challenge,
                                  const vlb_t *device_id, const vlb_t *reg_type,
                                  const vlb_t *reg_info, const vlb_t *idlist, const vlb_t *level,
                                  const vlb_t *ext_info, const vlb_t *sign_algorithm,
                                  IFAA_RegRespSigner signer, vlb_t *response);

typedef IFAA_Result (*IFAA_AuthRespSigner)(const char *token, uint32_t token_len,
                                           const uint8_t *source, uint32_t src_len,
                                           uint8_t *sig, uint32_t *sig_len, IFAA_AsymKeyAndType *key);

EXTERNC IFAA_Result generate_auth_response(const vlb_t *auth_token,
                                   const vlb_t *challenge, const vlb_t *device_id,
                                   const vlb_t *auth_type, const vlb_t *auth_info,
                                   const vlb_t *idlist, 
                                   const vlb_t *level, const vlb_t *ext_info,
                                   const vlb_t *sign_algorithm,
                                   IFAA_AuthRespSigner signer, IFAA_AsymKeyAndType *key, vlb_t *response);

#endif //IFAACLIENTTESTAPP_IFAA_TLV_PARSER_H
