/*
 * SPDX-FileCopyrightText: Copyright (C) Frickly Systems GmbH
 * SPDX-FileCopyrightText: Copyright (C) MBition GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef ARDEP_UDS_MACRO_H
#define ARDEP_UDS_MACRO_H

#ifndef _UDS_CAT
#define _UDS_CAT(a, b) a##b
#endif

#ifndef _UDS_CAT_EXPAND
#define _UDS_CAT_EXPAND(a, b) _UDS_CAT(a, b)
#endif

#ifndef _UDS_UNIQUE_REGISTRATION_NAME
#define _UDS_CAT_4(a, b, c, d) a##b##c##d
#define _UDS_CAT_4_EXP(a, b, c, d) _UDS_CAT_4(a, b, c, d)

#define _UDS_UNIQUE_REGISTRATION_NAME(category) \
  _UDS_CAT_4_EXP(__uds_registration##category##_, __COUNTER__, _l, __LINE__)
#endif

// #region READ_DTC_INFORMATION

// clang-format off

/**
 * @brief Register a new read dtc information event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the `_act` action should be executed
 * @param _act Execute the event handler for the event
 * @param _subfunc_id The subfunction ID to register the handler for
 * @param _user_context Optional context provided by the user
 */
#define UDS_REGISTER_READ_DTC_INFO_HANDLER(                                         \
  _instance,                                                                        \
  _check,                                                                           \
  _act,                                                                             \
  _subfunc_id,                                                                      \
  _user_context                                                                     \
)                                                                                   \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                       \
      /* Use a counter to generate unique names for the iterable section */         \
        _UDS_CAT_EXPAND(__uds_registration_id_read_dtc_info, __COUNTER__)) = {      \
    .instance = _instance,                                                          \
    .type = UDS_REGISTRATION_TYPE__READ_DTC_INFO,                                   \
    .read_dtc = {                                                                   \
      .user_context = _user_context,                                                \
      .sub_function = _subfunc_id,                                                  \
      .actor = {                                                                    \
        .check = _check,                                                            \
        .action = _act,                                                             \
      },                                                                            \
    }                                                                               \
  };

// clang-format on

/* Count 1..24 varargs */
#define _UDS_VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
                           _13, _14, _15, _16, _17, _18, _19, _20, _21, _22,  \
                           _23, _24, N, ...)                                  \
  N
#define _UDS_VA_NARGS(...)                                                    \
  _UDS_VA_NARGS_IMPL(__VA_ARGS__, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \
                     13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

/* Base "apply one" primitive */
#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_ONE(_inst, _chk, _act, _ctx, \
                                                      _sf)                     \
  UDS_REGISTER_READ_DTC_INFO_HANDLER(_inst, _chk, _act, _sf, _ctx)

/* Unrolled fan-out (1..27). Each line ends up at file scope just like the
 * original) */
#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s1) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_ONE(i, k, a, c, s1)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_2(i, k, a, c, s1, s2) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s1)           \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s2)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_3(i, k, a, c, s1, s2, s3) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_2(i, k, a, c, s1, s2)           \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s3)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_4(i, k, a, c, s1, s2, s3, \
                                                    s4)                     \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_3(i, k, a, c, s1, s2, s3)       \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s4)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_5(i, k, a, c, s1, s2, s3, \
                                                    s4, s5)                 \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_4(i, k, a, c, s1, s2, s3, s4)   \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s5)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_6(i, k, a, c, s1, s2, s3,   \
                                                    s4, s5, s6)               \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_5(i, k, a, c, s1, s2, s3, s4, s5) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s6)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_7(i, k, a, c, s1, s2, s3,   \
                                                    s4, s5, s6, s7)           \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_6(i, k, a, c, s1, s2, s3, s4, s5, \
                                              s6)                             \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s7)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_8(i, k, a, c, s1, s2, s3,   \
                                                    s4, s5, s6, s7, s8)       \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_7(i, k, a, c, s1, s2, s3, s4, s5, \
                                              s6, s7)                         \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s8)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_9(i, k, a, c, s1, s2, s3,   \
                                                    s4, s5, s6, s7, s8, s9)   \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_8(i, k, a, c, s1, s2, s3, s4, s5, \
                                              s6, s7, s8)                     \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s9)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_10(                         \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10)                      \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_9(i, k, a, c, s1, s2, s3, s4, s5, \
                                              s6, s7, s8, s9)                 \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s10)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_11(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11)                  \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_10(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10)            \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s11)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_12(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12)             \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_11(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11)       \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s12)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_13(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13)        \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_12(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11, s12)  \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s13)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_14(                        \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_13(                              \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13)    \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s14)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_15(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15)                                                                       \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_14(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14) \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s15)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_16(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16)                                                                  \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_15(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11, s12,  \
                                               s13, s14, s15)                  \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s16)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_17(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17)                                                             \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_16(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11, s12,  \
                                               s13, s14, s15, s16)             \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s17)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_18(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18)                                                        \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_17(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11, s12,  \
                                               s13, s14, s15, s16, s17)        \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s18)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_19(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19)                                                   \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_18(i, k, a, c, s1, s2, s3, s4, s5, \
                                               s6, s7, s8, s9, s10, s11, s12,  \
                                               s13, s14, s15, s16, s17, s18)   \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s19)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_20(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19, s20)                                              \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_19(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, \
      s15, s16, s17, s18, s19)                                                 \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s20)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_21(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19, s20, s21)                                         \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_20(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, \
      s15, s16, s17, s18, s19, s20)                                            \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s21)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_22(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19, s20, s21, s22)                                    \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_21(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, \
      s15, s16, s17, s18, s19, s20, s21)                                       \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s22)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_23(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19, s20, s21, s22, s23)                               \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_22(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, \
      s15, s16, s17, s18, s19, s20, s21, s22)                                  \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s23)

#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_24(                          \
    i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14,   \
    s15, s16, s17, s18, s19, s20, s21, s22, s23, s24)                          \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_23(                                \
      i, k, a, c, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, \
      s15, s16, s17, s18, s19, s20, s21, s22, s23)                             \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_1(i, k, a, c, s24)

/* Dispatcher */
#define _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_DISPATCH(n, i, k, a, c, ...) \
  _UDS_CAT_EXPAND(_UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_, n)(i, k, a, c,   \
                                                                 __VA_ARGS__)

// clang-format off


/**
 * @brief Register a new read dtc information event handler for several subfunction IDs
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the `_act` action should be executed
 * @param _act Execute the event handler for the event
 * @param _user_context Optional context provided by the user
 * @param ... List of subfunction IDs to register the handler for
 */
#define UDS_REGISTER_READ_DTC_INFO_HANDLER_MANY(          \
  _instance,                                              \
  _check,                                                 \
  _act,                                                   \
  _user_context,                                          \
  ...                                                     \
)                                                         \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_DISPATCH(     \
      _UDS_VA_NARGS(__VA_ARGS__),                         \
      _instance,                                          \
      _check,                                             \
      _act,                                               \
      _user_context,                                      \
      __VA_ARGS__                                         \
)


/**
 * @brief Register a new read dtc information event handler for all subfunction IDs
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the `_act` action should be executed
 * @param _act Execute the event handler for the event
 * @param _user_context Optional context provided by the user
 */
#define UDS_REGISTER_READ_DTC_INFO_HANDLER_ALL(             \
  _instance,                                                \
  _check,                                                   \
  _act,                                                     \
  _user_context                                             \
)                                                           \
  _UDS_REGISTER_READ_DTC_INFO_HANDLER_APPLY_DISPATCH(       \
      24,                                                   \
      _instance,                                            \
      _check,                                               \
      _act,                                                 \
      _user_context,                                        \
      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, \
      0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x14, 0x15, 0x16, 0x17, \
      0x18, 0x19, 0x1A, 0x42, 0x55, 0x56                    \
)

// clang-format on

// #endregion READ_DTC_INFORMATION

// #region MEMORY_BY_ADDRESS

// clang-format off

/**
 * @brief Register a new memory by address event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _read_check Check if the `_read` action should be executed
 * @param _read Execute a read for the event
 * @param _write_check Check if the `_write` action should be executed
 * @param _write Execute a write for the event
 * @param _user_context Optional context provided by the user
 */
#define UDS_REGISTER_MEMORY_HANDLER(                                          \
  _instance,                                                                  \
  _read_check,                                                                \
  _read,                                                                      \
  _write_check,                                                               \
  _write,                                                                     \
  _user_context                                                               \
)                                                                             \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                 \
      /* Use a counter to generate unique names for the iterable section */   \
        _UDS_UNIQUE_REGISTRATION_NAME(memory)) = {                            \
    .instance = _instance,                                                    \
    .type = UDS_REGISTRATION_TYPE__MEMORY,                                    \
    .memory = {                                                               \
      .user_context = _user_context,                                          \
      .read = {                                                               \
        .check = _read_check,                                                 \
        .action = _read,                                                      \
      },                                                                      \
      .write = {                                                              \
        .check = _write_check,                                                \
        .action = _write,                                                     \
      },                                                                      \
    }                                                                         \
  };

/**
 * @brief Register memory by address event handler with ability to read/write
 *        to/from flash and ram.
 */  
#define UDS_REGISTER_MEMORY_DEFAULT_HANDLER(_instance)                        \
  UDS_REGISTER_MEMORY_HANDLER(                                                \
    _instance,                                                                \
    uds_check_default_memory_by_addr_read,                                    \
    uds_action_default_memory_by_addr_read,                                   \
    uds_check_default_memory_by_addr_write,                                   \
    uds_action_default_memory_by_addr_write,                                  \
    NULL                                                                      \
  )

// clang-format on

// #endregion MEMORY_BY_ADDRESS

// #region ECU_RESET

// clang-format off



/**
 * @brief Register a new ecu reset event handler
 * 
 * @details The `UDS_EVT_DoScheduledReset` event is triggered after the 
 *          response to the `UDS_EVT_EcuReset` event is send and the wait
 *          duration has elapsed
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _reset_type type of reset as defined in ISO 14229-1 10.3.2.1
 * @param _ecu_reset_check Check if the `_ecu_reset` action should be executed
 * @param _ecu_reset Execute the `_ecu_reset` action for the event
 * @param _do_scheduled_reset_check Check if the `_do_scheduled_reset` action
 *        should be executed
 * @param _do_scheduled_reset Execute the `_do_scheduled_reset` action for the
 *        event
 * @param _user_context Optional context provided by the user
 */
#define UDS_REGISTER_ECU_RESET_HANDLER(                                       \
  _instance,                                                                  \
  _reset_type,                                                                \
  _ecu_reset_check,                                                           \
  _ecu_reset,                                                                 \
  _do_scheduled_reset_check,                                                  \
  _do_scheduled_reset,                                                        \
  _user_context                                                               \
)                                                                             \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                 \
        _UDS_UNIQUE_REGISTRATION_NAME(ecu_reset)) = {                         \
    .instance = _instance,                                                    \
    .type = UDS_REGISTRATION_TYPE__ECU_RESET,                                 \
    .ecu_reset = {                                                            \
      .user_context = _user_context,                                          \
      .type = _reset_type,                                                    \
      .ecu_reset = {                                                          \
        .check = _ecu_reset_check,                                            \
        .action = _ecu_reset,                                                 \
      },                                                                      \
      .execute_scheduled_reset = {                                            \
        .check = _do_scheduled_reset_check,                                   \
        .action = _do_scheduled_reset,                                        \
      }                                                                       \
    }                                                                         \
  };

/**
 * @brief Register the default ECU Reset event handler for a hard reset.
 * 
 * @param _instance Pointer to associated the UDS server instance
 */
#define UDS_REGISTER_ECU_DEFAULT_HARD_RESET_HANDLER(                         \
  _instance                                                                  \
)                                                                            \
  UDS_REGISTER_ECU_RESET_HANDLER(                                            \
    _instance,                                                               \
    ECU_RESET__HARD,                                                         \
    uds_check_ecu_hard_reset,                                                \
    uds_action_ecu_hard_reset,                                               \
    uds_check_execute_scheduled_reset,                                       \
    uds_action_execute_scheduled_reset,                                      \
    NULL                                                                     \
  )

// clang-format on

// #endregion ECU_RESET

// #region READ_WRITE_BY_IDENTIFIER

// clang-format off

/**
 * @brief Register a new static data identifier
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _data_id The data identifier to register the handler for
 * @param _data_ptr Custom context or data to handle the event
 * @param _read_check Check if the `_read` action should be executed
 * @param _read Execute a read for the event
 * @param _write_check Check if the `_write` action should be executed
 * @param _write Execute a write for the event
 * @param _io_control_check Check if the `_io_control` action should be executed
 * @param _io_control Act an io control event
 * @param _user_context Optional context provided by the user
 * 
 * @note: @p _write_check and @p _write are optional. Set to NULL for read-only
 *        data identifier
 *
 * @note: @p _io_control_check and @p _io_control are optional.
 *        Set to NULL for to make this data identifier not I/O controllable
 */
#define UDS_REGISTER_DATA_BY_IDENTIFIER_HANDLER(                      \
  _instance,                                                          \
  _data_id,                                                           \
  _data_ptr,                                                          \
  _read_check,                                                        \
  _read,                                                              \
  _write_check,                                                       \
  _write,                                                             \
  _io_control_check,                                                  \
  _io_control,                                                        \
  _user_context                                                       \
)                                                                     \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                         \
        _UDS_CAT_EXPAND(__uds_registration_id, _data_id)) = {         \
    .instance = _instance,                                            \
    .type = UDS_REGISTRATION_TYPE__DATA_IDENTIFIER,                   \
    .data_identifier = {                                              \
      .user_context = _user_context,                                  \
      .data = _data_ptr,                                              \
      .data_id = _data_id,                                            \
      .read = {                                                       \
        .check = _read_check,                                         \
        .action = _read,                                              \
      },                                                              \
      .write = {                                                      \
        .check = _write_check,                                        \
        .action = _write,                                             \
      },                                                              \
      .io_control = {                                                 \
        .check = _io_control_check,                                   \
        .action = _io_control,                                        \
      },                                                              \
    },                                                                \
  };

// clang-format on

// #endregion READ_WRITE_BY_IDENTIFIER

// #region DIAG_SESSION_CTRL

// clang-format off

/**
 * @brief Register a new static data identifier
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _diag_session_ctrl_check Check if the `_diag_session_ctrl` action should be executed
 * @param _diag_session_ctrl Execute a read for the event
 * @param _session_timeout_check Check if the `_session_timeout` action should be executed
 * @param _session_timeout Execute a write for the event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_DIAG_SESSION_CTRL_HANDLER(                                \
  _instance,                                                                   \
  _diag_session_ctrl_check,                                                    \
  _diag_session_ctrl,                                                          \
  _session_timeout_check,                                                      \
  _session_timeout,                                                            \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(diag_session)) = { \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__DIAG_SESSION_CTRL,                          \
    .diag_session_ctrl = {                                                     \
      .user_context = _user_context,                                           \
      .diag_sess_ctrl = {                                                      \
        .check = _diag_session_ctrl_check,                                     \
        .action = _diag_session_ctrl,                                          \
      },                                                                       \
      .session_timeout = {                                                     \
        .check = _session_timeout_check,                                       \
        .action = _session_timeout,                                            \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion DIAG_SESSION_CTRL

// #region CLEAR_DIAGNOSTIC_INFORMATION

// clang-format off

/**
 * @brief Register a new clear diagnostic event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the action should be executed
 * @param _act Execute the handler for the event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_CLEAR_DIAG_INFO_HANDLER(                                  \
  _instance,                                                                   \
  _check,                                                                      \
  _act,                                                                        \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(clear_diag_info)) = {                    \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__CLEAR_DIAG_INFO,                            \
    .clear_diagnostic_information = {                                          \
      .user_context = _user_context,                                           \
      .actor = {                                                               \
        .check = _check,                                                       \
        .action = _act,                                                        \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion CLEAR_DIAGNOSTIC_INFORMATION

// #region ROUTINE_CONTROL

// clang-format off

/**
 * @brief Register a new routine control event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the action should be executed
 * @param _act Execute the handler for the event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_ROUTINE_CONTROL_HANDLER(                                  \
  _instance,                                                                   \
  _routine_id,                                                                 \
  _check,                                                                      \
  _act,                                                                        \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(routine_control)) = {                    \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__ROUTINE_CONTROL,                            \
    .routine_control = {                                                       \
      .user_context = _user_context,                                           \
      .routine_id = _routine_id,                                               \
      .actor = {                                                               \
        .check = _check,                                                       \
        .action = _act,                                                        \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion ROUTINE_CONTROL

// #region SECURITY_ACCESS

// clang-format off

/**
 * @brief Register a new security access event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _request_seed_check Check if the associated action should be executed
 * @param _request_seed_act Execute the handler for the request seed event
 * @param _validate_key_check Check if the associated action should be executed
 * @param _validate_key_act Execute the handler for the validate key event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_SECURITY_ACCESS_HANDLER(                                  \
  _instance,                                                                   \
  _request_seed_check,                                                         \
  _request_seed_act,                                                           \
  _validate_key_check,                                                         \
  _validate_key_act,                                                           \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(security_access)) = {                    \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__SECURITY_ACCESS,                            \
    .security_access = {                                                       \
      .user_context = _user_context,                                           \
      .request_seed = {                                                        \
        .check = _request_seed_check,                                          \
        .action = _request_seed_act,                                           \
      },                                                                       \
      .validate_key = {                                                        \
        .check = _validate_key_check,                                          \
        .action = _validate_key_act,                                           \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion SECURITY_ACCESS

// #region COMMUNICATION_CONTROL

// clang-format off

/**
 * @brief Register a new communication control event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the associated action should be executed
 * @param _act Execute the handler for the communication control event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_COMMUNICATION_CONTROL_HANDLER(                            \
  _instance,                                                                   \
  _check,                                                                      \
  _act,                                                                        \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(comm_ctrl)) = {                          \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__COMMUNICATION_CONTROL,                      \
    .communication_control = {                                                 \
      .user_context = _user_context,                                           \
      .actor = {                                                               \
        .check = _check,                                                       \
        .action = _act,                                                        \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion COMMUNICATION_CONTROL

// #region CONTROL_DTC_SETTING

// clang-format off

/**
 * @brief Register a new control DTC setting event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the associated action should be executed
 * @param _act Execute the handler for the control DTC setting event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_CONTROL_DTC_SETTING_HANDLER(                                  \
  _instance,                                                                       \
  _check,                                                                          \
  _act,                                                                            \
  _user_context                                                                    \
)                                                                                  \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                      \
        _UDS_UNIQUE_REGISTRATION_NAME(control_dtc_setting)) = {                    \
    .instance = _instance,                                                         \
    .type = UDS_REGISTRATION_TYPE__CONTROL_DTC_SETTING,                            \
    .control_dtc_setting = {                                                       \
      .user_context = _user_context,                                               \
      .actor = {                                                                   \
        .check = _check,                                                           \
        .action = _act,                                                            \
      },                                                                           \
    },                                                                             \
  };

// clang-format on

// #endregion CONTROL_DTC_SETTING

// #region DYNAMICALLY_DEFINE_DATA_IDS

// clang-format off

/**
 * @brief Register a new dynamically define data IDs event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the associated action should be executed
 * @param _act Execute the handler for the dynamically define data IDs event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_DYNAMICALLY_DEFINE_DATA_IDS_HANDLER(                      \
  _instance,                                                                   \
  _check,                                                                      \
  _act,                                                                        \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_CAT_EXPAND(__uds_registration_dyn_data_ids_, __COUNTER__)) = {    \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__DYNAMIC_DEFINE_DATA_IDS,                    \
    .dynamically_define_data_ids = {                                           \
      .user_context = _user_context,                                           \
      .dynamic_registration_id_list = SYS_SLIST_STATIC_INIT(                   \
        &_UDS_CAT_EXPAND(__uds_registration_dyn_data_ids_, __COUNTER__ - 1)    \
          .dynamically_define_data_ids.dynamic_registration_id_list            \
      ),                                                                       \
      .actor = {                                                               \
        .check = _check,                                                       \
        .action = _act,                                                        \
      },                                                                       \
    },                                                                         \
  };

/**
 * @brief Register the default dynamically define data IDs event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 */
#define UDS_REGISTER_DYNAMICALLY_DEFINE_DATA_IDS_DEFAULT_HANDLER(            \
  _instance                                                                  \
)                                                                            \
  UDS_REGISTER_DYNAMICALLY_DEFINE_DATA_IDS_HANDLER(                          \
    _instance,                                                               \
    uds_check_default_dynamically_define_data_ids,                           \
    uds_action_default_dynamically_define_data_ids,                          \
    NULL                                                                     \
  )

// clang-format on

// #endregion DYNAMICALLY_DEFINE_DATA_IDS

// #region Authentication

// clang-format off

/**
 * @brief Register a new authentication event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _auth_check Check if the associated action should be executed
 * @param _auth_act Execute the handler for the authentication event
 * @param _timeout_check Check if the associated action should be executed
 * @param _timeout_act Execute the handler for the authentication timeout event
 * @param _user_context Optional context provided by the user
 * 
 */
#define UDS_REGISTER_AUTHENTICATION_HANDLER(                                   \
  _instance,                                                                   \
  _auth_check,                                                                 \
  _auth_act,                                                                   \
  _timeout_check,                                                              \
  _timeout_act,                                                                \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_UNIQUE_REGISTRATION_NAME(authentication)) = {                     \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__AUTHENTICATION,                             \
    .auth = {                                                                  \
      .user_context = _user_context,                                           \
      .auth = {                                                                \
        .check = _auth_check,                                                  \
        .action = _auth_act,                                                   \
      },                                                                       \
      .timeout = {                                                             \
        .check = _timeout_check,                                               \
        .action = _timeout_act,                                                \
      },                                                                       \
    },                                                                         \
  };

// clang-format on

// #endregion Authentication

#ifdef CONFIG_UDS_USE_LINK_CONTROL

// #region LINK_CONTROL

// clang-format off

/**
 * @brief Register a new link control event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * @param _check Check if the associated action should be executed
 * @param _act Execute the handler for the dynamically define data IDs event
 * @param _user_context Optional context provided by the user
 * 
 * @note Note that the link settings should be reset after an ecu_reset or session timeout event.
 *       This must be handled separately in the event handlers for these events and is not part of
 *       this registration.
 * 
 * @note When using link settings, you should set the suppress response bit on the request that
 *       triggers a change in the link settings (e.g. ecu reset or link control subfunction 0x03).
 *       The response is send after the event is emitted and thus can lead to communication
 *       problems when participants use different settings during transition.
 *
 */
#define UDS_REGISTER_LINK_CONTROL_HANDLER(                                     \
  _instance,                                                                   \
  _check,                                                                      \
  _act,                                                                        \
  _user_context                                                                \
)                                                                              \
  STRUCT_SECTION_ITERABLE(uds_registration_t,                                  \
        _UDS_CAT_EXPAND(__uds_registration_link_control_, __COUNTER__)) = {    \
    .instance = _instance,                                                     \
    .type = UDS_REGISTRATION_TYPE__LINK_CONTROL,                               \
    .link_control = {                                                          \
      .user_context = _user_context,                                           \
      .actor = {                                                               \
        .check =  _check,                                                      \
        .action = _act,                                                        \
      },                                                                       \
    },                                                                         \
  };

/**
 * @brief Register the default Link Control event handler
 * 
 * @param _instance Pointer to associated the UDS server instance
 * 
 * @note The default handler required handling of change diagnostic session
 *       events so don't consume these events if you use this feature
 */
#define UDS_REGISTER_LINK_CONTROL_DEFAULT_HANDLER(     \
  _instance                                            \
)                                                      \
  UDS_REGISTER_LINK_CONTROL_HANDLER(                   \
    _instance,                                         \
    uds_check_default_link_control,                    \
    uds_action_default_link_control,                   \
    NULL                                               \
  )                                                    \
  UDS_REGISTER_DIAG_SESSION_CTRL_HANDLER(              \
  _instance,                                           \
  uds_check_default_link_control_change_diag_session,  \
  uds_action_default_link_control_change_diag_session, \
  uds_check_default_link_control_change_diag_session,  \
  uds_action_default_link_control_change_diag_session, \
  NULL                                                 \
)

// clang-format on

// #endregion LINK_CONTROL

#endif  // CONFIG_UDS_USE_LINK_CONTROL

#endif  // ARDEP_UDS_MACRO_H
