#ifndef LIP_OPCUA_BINARY_TYPES_PROCBUF_H
#define LIP_OPCUA_BINARY_TYPES_PROCBUF_H

#include "lip_opcua_binary_types_parse.h"
#include "lip/app/opcua/types/lip_opcua_types.h"
#include "lip/app/opcua/types/lip_opcua_tstmp.h"
#include "lip/app/opcua/types/lip_opcua_variant.h"
#include "lip/app/opcua/types/lip_opcua_datavalue.h"
#include "lip/app/opcua/types/lip_opcua_nodeid.h"
#include "lip/app/opcua/types/lip_opcua_extobj.h"
#include "lip/app/opcua/types/lip_opcua_readvalueid.h"
#include "lip/app/opcua/types/lip_opcua_viewdescr.h"
#include "lip/app/opcua/types/lip_opcua_struct.h"
#include "lip/app/opcua/types/lip_opcua_enum.h"
#include "lip/app/opcua/types/struct/lip_opcua_build_info.h"
#include "lip/app/opcua/types/struct/lip_opcua_server_status.h"
#include "lip/app/opcua/types/lip_opcua_data_change_filter.h"
#include "lip/app/opcua/types/lip_opcua_types_da.h"
#include "lip/app/opcua/lip_opcua_svc_proto_defs.h"
#include "lip/app/opcua/lip_opcua_err_codes.h"


struct st_lip_opcua_session_ctx;

typedef struct st_lip_proc_buf {
    uint8_t *start;
    uint8_t *cur;
    uint8_t *end;
} t_lip_proc_buf;


static inline t_lip_opcua_err lip_opcua_procbuf_get_avsize_check(const t_lip_proc_buf *buf, uint32_t size) {
    return (buf->cur + size) > buf->end ?  LIP_OPCUA_ERR_BAD_DECODING_ERROR : LIP_OPCUA_ERR_GOOD;
}

static inline t_lip_opcua_err lip_opcua_procbuf_put_avsize_check(const t_lip_proc_buf *buf, uint32_t size) {
    return (buf->cur + size) > buf->end ?  LIP_OPCUA_ERR_BAD_ENCODING_ERROR : LIP_OPCUA_ERR_GOOD;
}

static inline void lip_procbuf_init(t_lip_proc_buf *buf, uint8_t *data, int size) {
    buf->start = buf->cur = data;
    buf->end = buf->start + size;
}

static inline void lip_procbuf_next(t_lip_proc_buf *buf, int size) {
    buf->cur += size;
}

static inline int lip_procbuf_avsize(const t_lip_proc_buf *buf) {
    return buf->end - buf->cur;
}

t_lip_opcua_err lip_opcua_procbuf_get_uint8(t_lip_proc_buf *buf, uint8_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_uint8(t_lip_proc_buf *buf, uint8_t val);
t_lip_opcua_err lip_opcua_procbuf_get_int8(t_lip_proc_buf *buf, int8_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_int8(t_lip_proc_buf *buf, int8_t val);
t_lip_opcua_err lip_opcua_procbuf_get_uint16(t_lip_proc_buf *buf, uint16_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_uint16(t_lip_proc_buf *buf, uint16_t val);
t_lip_opcua_err lip_opcua_procbuf_get_int16(t_lip_proc_buf *buf, int16_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_int16(t_lip_proc_buf *buf, int16_t val);
t_lip_opcua_err lip_opcua_procbuf_get_int32(t_lip_proc_buf *buf, int32_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_int32(t_lip_proc_buf *buf, int32_t val);
t_lip_opcua_err lip_opcua_procbuf_get_uint32(t_lip_proc_buf *buf, uint32_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_uint32(t_lip_proc_buf *buf, uint32_t val);
t_lip_opcua_err lip_opcua_procbuf_get_uint64(t_lip_proc_buf *buf, uint64_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_uint64(t_lip_proc_buf *buf, uint64_t val);
t_lip_opcua_err lip_opcua_procbuf_get_int64(t_lip_proc_buf *buf, int64_t *val);
t_lip_opcua_err lip_opcua_procbuf_put_int64(t_lip_proc_buf *buf, int64_t val);
t_lip_opcua_err lip_opcua_procbuf_get_double(t_lip_proc_buf *buf, double *val);
t_lip_opcua_err lip_opcua_procbuf_put_double(t_lip_proc_buf *buf, double val);
t_lip_opcua_err lip_opcua_procbuf_get_float(t_lip_proc_buf *buf, float *val);
t_lip_opcua_err lip_opcua_procbuf_put_float(t_lip_proc_buf *buf, float val);
t_lip_opcua_err lip_opcua_procbuf_get_bool(t_lip_proc_buf *buf, bool *val);
t_lip_opcua_err lip_opcua_procbuf_put_bool(t_lip_proc_buf *buf, bool val);


#define         lip_opcua_procbuf_get_duration      lip_opcua_procbuf_get_double
#define         lip_opcua_procbuf_put_duration      lip_opcua_procbuf_put_double
#define         lip_opcua_procbuf_get_counter       lip_opcua_procbuf_get_uint32
#define         lip_opcua_procbuf_put_counter       lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_intid         lip_opcua_procbuf_get_uint32
#define         lip_opcua_procbuf_put_intid         lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_status        lip_opcua_procbuf_get_uint32
#define         lip_opcua_procbuf_put_status        lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_enum          lip_opcua_procbuf_get_uint32
#define         lip_opcua_procbuf_put_enum          lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_index         lip_opcua_procbuf_get_uint32
#define         lip_opcua_procbuf_put_index         lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_arrsize       lip_opcua_procbuf_get_int32
#define         lip_opcua_procbuf_put_arrsize       lip_opcua_procbuf_put_int32
#define         lip_opcua_procbuf_put_objlen        lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_get_objlen        lip_opcua_procbuf_put_uint32
#define         lip_opcua_procbuf_put_arrsize_null(buf)  lip_opcua_procbuf_put_arrsize(buf, -1)
#define         lip_opcua_procbuf_put_diagnostic_info_null(buf) lip_opcua_procbuf_put_uint8(buf, 0)


t_lip_opcua_err lip_opcua_procbuf_put_objlen_deltabuf(const t_lip_proc_buf *buf, t_lip_proc_buf *objlen_buf);


t_lip_opcua_err lip_opcua_procbuf_put_double_arr(t_lip_proc_buf *buf, const double *arr, int32_t size);



t_lip_opcua_err lip_opcua_procbuf_get_datetime(t_lip_proc_buf *buf, t_lip_opcua_datetime *tstmp);
t_lip_opcua_err lip_opcua_procbuf_put_datetime(t_lip_proc_buf *buf, t_lip_opcua_datetime tstmp);
t_lip_opcua_err lip_opcua_procbuf_get_string(t_lip_proc_buf *buf, t_lip_opcua_string_ptr *str);
t_lip_opcua_err lip_opcua_procbuf_put_string(t_lip_proc_buf *buf, const t_lip_opcua_string_ptr *str);

t_lip_opcua_err lip_opcua_procbuf_get_loc_string(t_lip_proc_buf *buf, t_lip_opcua_loc_string_ptr *locstr);
t_lip_opcua_err lip_opcua_procbuf_put_loc_string(t_lip_proc_buf *buf, const t_lip_opcua_loc_string_ptr *locstr);
t_lip_opcua_err lip_opcua_procbuf_put_loc_string_from_list(t_lip_proc_buf *buf, const t_lip_opcua_loc_string_ptr_list *loclist, struct st_lip_opcua_session_ctx *session);

t_lip_opcua_err lip_opcua_procbuf_get_string_arr(t_lip_proc_buf *buf, t_lip_opcua_string_ptr_array *arr);
t_lip_opcua_err lip_opcua_procbuf_put_string_arr(t_lip_proc_buf *buf, const t_lip_opcua_string_ptr_array *arr);



t_lip_opcua_err lip_opcua_procbuf_get_qalified_name(t_lip_proc_buf *buf, t_lip_opcua_qualified_name *qname);
t_lip_opcua_err lip_opcua_procbuf_put_qalified_name(t_lip_proc_buf *buf, const t_lip_opcua_qualified_name *qname);




t_lip_opcua_err lip_opcua_procbuf_get_signature_data(t_lip_proc_buf *buf, t_lip_opcua_signature_data *sdata);
t_lip_opcua_err lip_opcua_procbuf_put_signature_data(t_lip_proc_buf *buf, const t_lip_opcua_signature_data *sdata);


t_lip_opcua_err lip_opcua_procbuf_get_nodeid(t_lip_proc_buf *buf, t_lip_opcua_nodeid *nodeid);
t_lip_opcua_err lip_opcua_procbuf_put_nodeid(t_lip_proc_buf *buf, const t_lip_opcua_nodeid *nodeid);
t_lip_opcua_err lip_opcua_procbuf_get_extobj_info(t_lip_proc_buf *buf, t_lip_opcua_extobj_info *exobj_info);
t_lip_opcua_err lip_opcua_procbuf_put_extobj(t_lip_proc_buf *buf, const t_lip_opcua_extobj_info *exobj_info);
t_lip_opcua_err lip_opcua_procbuf_put_extobj_info(t_lip_proc_buf *buf, const t_lip_opcua_nodeid *exobj_type, t_lip_proc_buf *body_len_buf);


t_lip_opcua_err lip_opcua_procbuf_get_variant(t_lip_proc_buf *buf, t_lip_opcua_variant *var);
t_lip_opcua_err lip_opcua_procbuf_put_variant(t_lip_proc_buf *buf, const t_lip_opcua_variant *var, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_get_datavalue(t_lip_proc_buf *buf, t_lip_opcua_data_value *var);
t_lip_opcua_err lip_opcua_procbuf_put_datavalue(t_lip_proc_buf *buf, const t_lip_opcua_data_value *var, t_lip_opcua_ret_tstmp_types tstmp_types, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_get_readvalueid(t_lip_proc_buf *buf, t_lip_opcua_read_value_id *rvalueid);
t_lip_opcua_err lip_opcua_procbuf_put_readvalueid(t_lip_proc_buf *buf, const t_lip_opcua_signature_data *sdata);

t_lip_opcua_err lip_opcua_procbuf_get_viewdescr(t_lip_proc_buf *buf, t_lip_opcua_view_descr *viewdescr);
t_lip_opcua_err lip_opcua_procbuf_get_data_change_filter(t_lip_proc_buf *buf, t_lip_opcua_data_change_filter *filter);


t_lip_opcua_err lip_opcua_procbuf_put_struct_field(t_lip_proc_buf *buf, const t_lip_opcua_struct_field *field, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_struct_def(t_lip_proc_buf *buf, const t_lip_opcua_struct_def *struct_def, struct st_lip_opcua_session_ctx *session);

t_lip_opcua_err lip_opcua_procbuf_put_enum_value(t_lip_proc_buf *buf, const t_lip_opcua_enum_value *enum_val, struct st_lip_opcua_session_ctx *session);

t_lip_opcua_err lip_opcua_procbuf_put_build_info(t_lip_proc_buf *buf, const t_lip_opcua_data_build_info *build_info, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_server_status(t_lip_proc_buf *buf, const t_lip_opcua_data_server_status *srvstatus, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_range(t_lip_proc_buf *buf, const t_lip_opcua_da_range *range, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_eu_info(t_lip_proc_buf *buf, const t_lip_opcua_da_eu_info *eu_info, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_complex_num(t_lip_proc_buf *buf, const t_lip_opcua_da_complex_num *complex_num, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_double_complex_num(t_lip_proc_buf *buf, const t_lip_opcua_da_double_complex_num *complex_num, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_axis_info(t_lip_proc_buf *buf, const t_lip_opcua_da_axis_info *axis_info, struct st_lip_opcua_session_ctx *session);
t_lip_opcua_err lip_opcua_procbuf_put_da_xv(t_lip_proc_buf *buf, const t_lip_opcua_da_xv *xv, struct st_lip_opcua_session_ctx *session);


#endif // LIP_OPCUA_BINARY_TYPES_PROCBUF_H
