#ifndef A330_ALP_PARSER_IF_H
#define A330_ALP_PARSER_IF_H

#include "net_buf.h"
#include "x_typedef.h"

typedef enum
{
    ALP_SUCCESS                        = 0,
    ALP_ERROR                          = 1,
    ALP_NULL_PTR                       = 2,
    ALP_BUF_UNDERFLOW                  = 3,
    ALP_PARSE_ERR_BASE_HDR             = 4,
    ALP_PARSE_ERR_INVALID_ENCAP_TYPE   = 5,
    ALP_PARSE_ERROR_ADD_HDR2           = 6,
    ALP_FAIL_LLS_CB                    = 7,
    ALP_CODE_FAIL_DATA_CB              = 8,
    ALP_FAIL_BAD_LLS_TYPE              = 9,
    ALP_FILTER_OUT                     = 10,
    ALP_FAIL_DECOMPRESS                = 11,
    ALP_FAIL_PACKT_TYPE_NOT_SUPPORT    = 12,
    ALP_NO_PAYLOAD_PRIVATE_PACKET      = 13,
    ALP_HANDLE_PRIV_PLP_ID_ERROR       = 14,
    ALP_FAIL_NO_PLP_CONTEXT            = 15,
    ALP_WAIT_FOR_CONTEXT_TO_ESTABLISH  = 16,
    ALP_FAIL_PARSE_RDT                 = 17,
    ALP_FAIL_INVALID_DECOMPRESSOR      = 18,
    ALP_SEGMENT_BUF_ERROR              = 19,
    ALP_FAIL_FILTER_ERROR              = 20,
    ALP_PRIVATE_PKT_PLP_ID             = 21,
    ALP_PRIVATE_PKT_PTP                = 22,
}ALP_RET_CODE_T;

typedef enum
{
    ALP_STRM_INVALID = 0x0,
    ALP_STRM_ENABLE  = 0x1,
    ALP_STRM_DISABLE = 0x2,
}ALP_STREAM_STATE_T;

typedef enum
{
    PARSER_INPUT_TYPE_ALP  = 0x0,
    PARSER_INPUT_TYPE_IP   = 0x1,
    PARSER_INPUT_TYPE_ROHC = 0x2,
    PARSER_INPUT_TYPE_PUD  = 0x3,
    PARSER_INPUT_TYPE_UNKONWN,
}alp_parser_input_packet_type_t;

typedef struct
{
    BOOL enable_sw_parse_rdt;
    BOOL enable_sw_deadaption;
    BOOL enable_sw_ptp_update;
}alp_sw_parser_config_t;

/*!!! TAKE CARE ON STRUCT MODIFICATION
 *
 * in order do shared buffer data handling between kernel->user
 * udp_ip_packet_descriptor_t must be all the same as
 * atsc30_udp_ip_packet_descriptor_t in x_atsc30_common.h and
 * mtatsc30_udp_ip_packet_descriptor_t in mtatsc30.h
 */
typedef struct
{
    UINT8  framer_idx;
    UINT8  plp_id;

    UINT8  SID_flag;
    UINT8  SID;

    UINT16 src_port;      //network byteorder
    UINT16 dst_port;      //network byteorder

    UINT32 src_addr;      //network byteorder
    UINT32 dst_addr;      //network byteorder

    UINT32 tag_id;        /*< private_data defined by mw attached to the stream>*/
    UINT32 pkt_id;        /*< pkt id set by driver>*/

    UINT32 pkt_start_ofst; /* Driver guarantee no buffer wrap around: i.e. pkt_start < pkt_end */
    UINT32 pkt_end_ofst;
}udp_ip_packet_descriptor_t;

/*!!! TAKE CARE ON STRUCT MODIFICATION
 *
 * used accross kernel and user space, members of the struct is well orgnazied to be 4 * 4 bytes,
 * avoiding padding and satisfying byte alignment for performance and easy handling concerns.
 */
typedef struct
{
    UINT8  plp_id;
    UINT8  framer_idx;
    UINT32 pkt_id;
    UINT32 pkt_start_ofst;
    UINT32 pkt_end_ofst;
}alp_packet_descriptor_t;

#define INVALID_ALP_STREAM_ID (-1)
typedef UINT8 alp_stream_ID;

typedef struct
{
    UINT8  plp_id;
    UINT8  ignore_plp_id;
    UINT8  compress_flag;
    UINT8  context_id;
    UINT8  SID_flag;
    UINT8  SID;

    ALP_STREAM_STATE_T  state;

    UINT16 src_port;      //network byteorder
    UINT16 dst_port;      //network byteorder
    UINT32 src_addr;      //network byteorder
    UINT32 dst_addr;      //network byteorder
    UINT16 src_port_mask; //network byteorder
    UINT16 dst_port_mask; //network byteorder
    UINT32 src_addr_mask; //network byteorder
    UINT32 dst_addr_mask; //network byteorder

    UINT32 priv_info;
    UINT32 pkt_cnt;
}alp_stream_t;

typedef struct
{
    UINT8  framer_idx;
    UINT8  sid;
    BOOL   sid_flag;
    UINT8  plp_id;
    UINT8  max_cid;
    UINT8  strm_idx;
    alp_parser_input_packet_type_t input_type;
}alp_parser_input_info_t;

typedef BOOL (*pfn_alp_parse_ip_output)(UINT8, const net_buf_t, const udp_ip_packet_descriptor_t * const);
typedef BOOL (*pfn_alp_parse_alp_raw_output_cb)(UINT8, const net_buf_t,  const alp_packet_descriptor_t *const);

typedef BOOL (*pfn_alp_parse_lls_output_cb)(const net_buf_t, alp_packet_descriptor_t *const);
typedef BOOL (*pfn_alp_parse_ptp_update_stc_cb)(UINT8, UINT64);

extern BOOL alp_parser_if_init(const UINT8 framer_idx,
                               const pfn_alp_parse_ip_output udp_ip_cb,
                               const pfn_alp_parse_alp_raw_output_cb alp_raw_cb,
                               const pfn_alp_parse_lls_output_cb pfn_lls_cb,
                               const pfn_alp_parse_ptp_update_stc_cb pfn_ptp_cb,
                               const alp_sw_parser_config_t sw_cfg);

extern VOID alp_parser_if_deinit(const UINT8 framer_idx);

extern alp_stream_ID alp_parser_if_set_stream(const UINT8 framer_idx, const alp_stream_t* const new_strm);
extern const alp_stream_t*  alp_parser_if_get_stream(const UINT8 framer_idx, alp_stream_ID strm_id);
extern BOOL alp_parser_if_update_stream_state(const UINT8 framer_idx,
                                              alp_stream_ID strm_id,
                                              ALP_STREAM_STATE_T state);

extern BOOL alp_parser_if_set_plp_id_filter(UINT8 framer_idx, const UINT8 *const plp_id_arr, UINT8 plp_cnt);
extern VOID alp_parser_if_clear_plp_id_filter(UINT8 framer_idx);

extern ALP_RET_CODE_T alp_parser_if_run(net_buf_t *const packet, const alp_parser_input_info_t *const input_info);

extern VOID alp_parser_if_collect_filter(const UINT8 framer_idx);

extern VOID alp_parser_if_collect_statistics(const UINT8 framer_idx);

#endif /* A330_ALP_PARSER_IF_H */
