#ifndef CAN_STACK_TYPES_H
#define CAN_STACK_TYPES_H

/* ============================================================================================== */
/*                                        CONFILICT TYPEDEF                                       */
/* ============================================================================================== */
#define CANTP_TRUE                                  (1U)
#define CANTP_FALSE                                 (0U)

#define CANTP_NULL                                  ((void *) 0)

#define CANTP_E_OK                                  (0U)
#define CANTP_E_NOT_OK                              (1U)

#define CANTP_HIGH                                  (1U)
#define CANTP_LOW                                   (0U)

#define CANTP_ON                                    (1U)
#define CANTP_OFF                                   (0U)

typedef signed char         cantp_s8;               /**< -128 .. +127                   */
typedef unsigned char       cantp_u8;               /**< 0 .. 255                       */
typedef signed short        cantp_s16;              /**< -32768 .. +32767               */
typedef unsigned short      cantp_u16;              /**<  0 .. 65535                    */
typedef signed long         cantp_s32;              /**< -2147483648 .. +2147483647     */
typedef unsigned long       cantp_u32;              /**<  0 .. 4294967295               */
typedef unsigned char       cantp_bool;

typedef cantp_u8 cantp_return_type;

/* ============================================================================================== */
#define CANTP_TX_DL_CHANGE_NUM                      (8U)
/*                                             TYPEDEF                                            */
/* ============================================================================================== */
typedef cantp_u16 pdu_id_type;

typedef cantp_u16 sdu_id_type;

typedef cantp_u16 cantp_time_type;

typedef cantp_u32 can_id_type;

typedef cantp_u32 buffer_length_type;

typedef cantp_u32 pdu_length_type;

typedef cantp_u8 cantp_pdu_dir_type;

/* ============================================================================================== */
/*                                              ENUM                                              */
/* ============================================================================================== */
typedef enum
{
    CANTP_FIFO_RES_SUCCESS,                         /**< Success */
    CANTP_FIFO_RES_ERRO_REGISTERED_SECOND,          /**< Fifo has already been allocated space */
    CANTP_FIFO_RES_INVALID_FIFOID,                  /**< Invalid FIFO ID */
    CANTP_FIFO_RES_OVERFLOW,                        /**< FIFO overflow */
    CANTP_FIFO_RES_NOT_ENOUGH_DATA_TO_COPY,         /**< Not enough data to copy */
    CANTP_FIFO_RES_PDU_IS_TRANSMITTING,             /**< Data is transmitting in FIFO */
    CANTP_FIFO_RES_PDU_IS_NOT_TRANSMITTING,         /**< No data is transmitting in FIFO */
    CANTP_FIFO_RES_NOT_ENOUGH_DATA_COPIED,          /**< Not enough data copied */
    CANTP_FIFO_RES_NO_SDU_IN_FIFO,                  /**< No SDU in FIFO */
    CANTP_FIFO_RES_NULL_POINTER,                    /**< Null pointer */
    CANTP_FIFO_RES_EMPTY,                           /**< Empty */
    CANTP_FIFO_RES_NO_MSG,                          /**< Transmit msg with pdu length setting to 0 */
    CANTP_FIFO_RES_MEM_NOT_ENOUGH,                  /**< The memory is not enough to copy sdu */
} cantp_fifo_res_type;

typedef enum
{
    CANTP_CORE_N_OK,                                /**< Success */
    CANTP_CORE_N_TIMEOUT_A,                         /**< Timeout at sender or receiver transmit frame */
    CANTP_CORE_N_TIMEOUT_Bs,                        /**< Timeout waiting for FC */
    CANTP_CORE_N_TIMEOUT_Cr,                        /**< Timeout waiting for CF */
    CANTP_CORE_N_WRONG_SN,                          /**< Incorrect sequence number in CF */
    CANTP_CORE_N_INVALID_FS,                        /**< Invalid FlowStatus */
    CANTP_CORE_N_UNEXP_PDU,                         /**< Unexpected PDU */
    CANTP_CORE_N_WFT_OVRN,                          /**< Wait for FC up to WFTmax */
    CANTP_CORE_N_BUFFER_OVFLW,                      /**< Buffer overflow */
    CANTP_CORE_N_ERROR                              /**< Error */
} cantp_core_res_type;

typedef enum
{
    CANTP_CORE_SF,                                  /**< Single frame */
    CANTP_CORE_FF,                                  /**< First frame */
    CANTP_CORE_CF,                                  /**< Continue frame */
    CANTP_CORE_FC                                   /**< Flow control frame */
} cantp_core_frame_type;

typedef enum
{
    CANTP_ADDR_TYPE_PHYSICAL        = 0U,           /**< Physical address */
    CANTP_ADDR_TYPE_FUNCTIONAL      = 1U,           /**< Functional address */
} cantp_addr_type;

typedef enum
{
    CANTP_ID_TYPE_STANDARD         = 0U,            /**< Standard can id, 11 bits */
    CANTP_ID_TYPE_EXTENDED         = 1U,            /**< Extended can id, 29 bits */
} cantp_id_type;

typedef enum
{
    CANTP_ADDR_FORMAT_NORMAL       = 0U,            /**< Address type: normal */
    CANTP_ADDR_FORMAT_FIXED_NORMAL = 1U,            /**< Address type: fixed normal */
    CANTP_ADDR_FORMAT_EXTENDED     = 2U,            /**< Address type: extended */
    CANTP_ADDR_FORMAT_MIXED        = 3U,            /**< Address type: mixed */
    CANTP_ADDR_FORMAT_ENHANCED     = 4U,            /**< Address type: enhanced */
} cantp_addr_format_type;


// TODO add param change function
typedef enum
{
    CANTP_PARAM_STMIN              = 0U,            /**< STmin */
    CANTP_PARAM_BS                 = 1U,            /**< Block size */
    /** TP_BC = 0x02U */
} tp_parameter_type;

typedef enum
{
    CANTP_BUF_REQ_OK                = 0x00U,        /**< Request buffer success */
    CANTP_BUF_REQ_NOT_OK            = 0x01U,        /**< request buffer failed */
    CANTP_BUF_REQ_BUSY              = 0x02U,        /**< Buffer is busy */
    CANTP_BUF_REQ_OVFL              = 0x03U         /**< Buffer overflow */
} buf_req_return_type;

typedef enum
{
    BUF_DATA_RX_OK = 0x00U,
    BUF_DATA_RX_RETRY = 0x01U,
} buf_indication_res_type;

/**
 * @brief This enumeration is reserved for future use in defining gateways
 */
typedef enum
{
    CANTP_DATA_CONF                = 0x00U,         /**< all tp has copied the data */
    CANTP_DATA_RETRY               = 0x01U,         /**< re-copy some data */
    CANTP_DATA_PENDING             = 0x02U          /**< previous copied data need to be remain */
} tp_data_state_type;

typedef enum
{
    CANTP_COPY_OK                 = 0x00U,          /**< One msg was copied success */
    CANTP_COPY_ERROR              = 0x01U,          /**< Error happens when copy msg */
    CANTP_COPY_EMPTY              = 0x02U,          /**< No msg in fifo */
    CANTP_COPY_MEM_NOT_ENOUGH     = 0x03U           /**< The given size was not enough */
} cantp_copy_res_type;

typedef enum
{
    CANSTACK_UNINIT = 0U,
    CANSTACK_INITED = 1U,
} cantp_status_type;

typedef enum {
    CANTP_HAL_TX_OK,                                /**< Transmit msg ok */
    CANTP_HAL_TX_NOT_OK,                            /**< Transmit msg err */
    CANTP_HAL_TX_BUSY,                               /**< Transmit msg with MB busy, try again later */
    CANTP_HAL_TX_WAIT                               /**< The MB is free to transmit msg */
} cantp_hal_tx_res_type;

/**
 * @brief The fellowing type is defined for cantp callback
 */
typedef void (*cantp_rx_indication_type)(pdu_id_type rxSduId, cantp_core_res_type res);
typedef void (*cantp_tx_confirmation_type)(pdu_id_type txSduId, cantp_core_res_type res);
/* ============================================================================================== */
/*                                             STRUCT                                             */
/* ============================================================================================== */
typedef struct
{
    cantp_u8* sduDataPtr;                           /**< Pointer point to data */
    cantp_u8* metaDataPtr;                          /**< Pointer point to meta data */
    pdu_length_type sduLength;                      /**< Data len */
} pdu_info_type_t;

typedef struct
{
    tp_data_state_type tpDataState;                 /**< Retry info */
    pdu_length_type txTpDataCnt;                    /**< Data len */
} retry_info_type_t;

typedef struct
{
    cantp_addr_type addrType;                       /**< Address type, function or physical */
    cantp_u8 compareByte;                           /**< Extra byte data for Mixed or Extended address format */
    cantp_u8 addrByte;                              /**< Extra byte data for Mixed or Extended address format */
    cantp_u8 inst;                                  /**< Actual used FLEX_CAN instance */
    cantp_u8 TX_DL;                                 /**< Configured tx data length */
    cantp_u8 SF_DL;                                 /**< Max single frame data length */
    cantp_bool padding;                             /**< whether enable padding for current channel */
    cantp_u8 paddingValue;                          /**< Padding value for current TP channel */
    cantp_u16 bs;                                   /**< Block Size */
    cantp_u16 maxWtf;                               /**< Max wait for frame count */
} cantp_ch_config_array_type_t;

typedef struct  {
    cantp_u16 nAs;                                  /**< Time for transmission of the CAN frame (any N_PDU) on the sender side */
    cantp_u16 nAr;                                  /**< Time for transmission of the CAN frame (any N_PDU) on the receiver side */
    cantp_u16 nBs;                                  /**< Time until reception of the next FlowControl N_PDU */
    cantp_u16 nBr;                                  /**< Time until transmission of the next FlowControl N_PDU */
    cantp_u16 nCr;                                  /**< Time until transmission of the next ConsecutiveFrame N_PDU */
    cantp_u16 nCs;                                  /**< Time until reception of the next Consecutive Frame N_PDU */
    cantp_u16 stMin;                                /**< The minimum time the sender is to wait between transmission of two CF N_PDUs. */
} cantp_time_array_type_t;


typedef struct {
    cantp_ch_config_array_type_t* chConfig;         /**< Pointer point to the configuration array */
    cantp_time_array_type_t* timeMap;               /**< Pointer point to the time configuration array */
    const cantp_u8* pciOffsetArray;                 /**< Pointer point to the pci offset array */
    cantp_rx_indication_type rxCallback;            /**< Pointer point to the callback function configured */
    cantp_tx_confirmation_type txCallback;          /**< Pointer point to the callback function configured */
} cantp_config_t;
#endif