#ifndef ISOTP_H
#define ISOTP_H

#include <stddef.h>
#include <stdint.h>

#define MAX_ISOTP_MESSAGES_IN_FLIGHT 10
#define ISOTP_FC_WAIT_TIMEOUT      1000    // Timeout for flow control frames (ms)
//#define ISOTP_PADDING 0xAA // optional padding byte

typedef enum : int16_t {
    ISOTP_OK = 0,
    ISOTP_ERROR = -1,
    ISOTP_DATA_TOO_LONG = -2,
    ISOTP_INVALID_PARAMETER = -3,
    ISOTP_TOO_MANY_MESSAGES = -4,
    ISOTP_MESSAGE_ALREADY_IN_FLIGHT = -5,
    ISOTP_NOT_FLOW_CONTROL = -6,
    ISOTP_CAN_TRANSMIT_ERROR = -7,
} isotp_status_t;

static inline const char *isotp_status_to_string(isotp_status_t status) {
    switch (status) {
        case ISOTP_OK: return "ISOTP_OK";
        case ISOTP_ERROR: return "ISOTP_ERROR";
        case ISOTP_DATA_TOO_LONG: return "ISOTP_DATA_TOO_LONG";
        case ISOTP_INVALID_PARAMETER: return "ISOTP_INVALID_PARAMETER";
        case ISOTP_TOO_MANY_MESSAGES: return "ISOTP_TOO_MANY_MESSAGES";
        case ISOTP_MESSAGE_ALREADY_IN_FLIGHT: return "ISOTP_MESSAGE_ALREADY_IN_FLIGHT";
        case ISOTP_NOT_FLOW_CONTROL: return "ISOTP_NOT_FLOW_CONTROL";
        case ISOTP_CAN_TRANSMIT_ERROR: return "ISOTP_CAN_TRANSMIT_ERROR";
        default: return "UNKNOWN_STATUS";
    }
}

isotp_status_t isotp_init();
[[gnu::access(read_only, 2, 3)]] isotp_status_t isotp_add_message(uint16_t id, const uint8_t *data, size_t datalen);
isotp_status_t isotp_update();
[[gnu::access(read_only, 2, 3)]] isotp_status_t isotp_handle_flow_control(uint16_t id, const uint8_t *data, size_t datalen);

#endif // ISOTP_H