/** 
 * @file    debug.h
 * @brief   DEBUG module
 * @author  Eric Xu
 * @date    Oct 15 2025
 * @version 0.0.1
 *
 * @section LICENSES
 * Copyright (C) Morgan Advanced Programmable Systems, Inc.
 */

#ifndef DEBUG_H_
#define DEBUG_H_

#include <zephyr/kernel.h>

#ifdef CONFIG_DBG_STATS
/*--------------------------------------------------------------------------------------------------
 * DEBUG VARIABLE
 *------------------------------------------------------------------------------------------------*/
extern atomic_t i2c_transfer_active;

extern volatile uint32_t fifo_read_task_counter;
extern volatile uint32_t read_shot_data_counter;
extern volatile uint32_t read_into_dummy_counter;
extern volatile uint32_t fifo_read_FTH_counter;
extern volatile uint32_t read_shot_data_after_fifo_read_counter;
extern volatile uint32_t fifo_waterM_total_hit_counter;
extern volatile uint32_t fifo_waterM_hit_counter;
extern volatile uint32_t fifo_overrun_counter;
extern volatile uint32_t unread_words_before_read;
extern volatile uint32_t unread_words_after_read;
extern volatile uint32_t max_unread_words_before_read;
extern volatile uint32_t max_unread_words_after_read;

extern volatile uint32_t imu_task_during_i2c_counter;
extern volatile uint32_t fsm_task_counter;
extern volatile uint32_t fsm_task_during_i2c_counter;
extern volatile uint32_t event_task_counter;
extern volatile uint32_t event_task_during_i2c_counter;


/*--------------------------------------------------------------------------------------------------
 * DEBUG MACRO
 *------------------------------------------------------------------------------------------------*/
#define DBG_STAT_INC(counter) counter++
#define DBG_STAT_INC_IF(condition, counter) do { if (condition) counter++; } while(0)
#define DBG_STAT_TRACK_MAX(current_value, max_value) \
    do { \
        __typeof__(current_value) _temp_val = (current_value); \
        if (_temp_val > (max_value)) { \
            (max_value) = _temp_val; \
        } \
    } while(0)

/* Thread-safe versions using stat_mutex */
#define DBG_STAT_INC_SAFE(counter, mutex) \
    do { \
        k_mutex_lock(&(mutex), K_FOREVER); \
        counter++; \
        k_mutex_unlock(&(mutex)); \
    } while(0)

#define DBG_STAT_INC_IF_SAFE(condition, counter, mutex) \
    do { \
        if (condition) { \
            k_mutex_lock(&(mutex), K_FOREVER); \
            counter++; \
            k_mutex_unlock(&(mutex)); \
        } \
    } while(0)

#define DBG_STAT_TRACK_VALUE_SAFE(current_value, latest_value, mutex) \
    do { \
        __typeof__(current_value) _temp_val = (current_value); \
        k_mutex_lock(&(mutex), K_FOREVER); \
            (latest_value) = _temp_val; \
        k_mutex_unlock(&(mutex)); \
    } while(0)

#define DBG_STAT_TRACK_MAX_SAFE(current_value, max_value, mutex) \
    do { \
        __typeof__(current_value) _temp_val = (current_value); \
        k_mutex_lock(&(mutex), K_FOREVER); \
        if (_temp_val > (max_value)) { \
            (max_value) = _temp_val; \
        } \
        k_mutex_unlock(&(mutex)); \
    } while(0)

#else
#define DBG_STAT_INC(counter)                                                  do {} while(0)
#define DBG_STAT_INC_IF(condition, counter)                                    do {} while(0)
#define DBG_STAT_TRACK_MAX(current_value, max_value)                           do {} while(0)
#define DBG_STAT_INC_SAFE(counter, mutex)                                      do {} while(0)
#define DBG_STAT_INC_IF_SAFE(condition, counter, mutex)                        do {} while(0)
#define DBG_STAT_TRACK_VALUE_SAFE(current_value, latest_value, mutex)          do {} while(0)
#define DBG_STAT_TRACK_MAX_SAFE(current_value, max_value, mutex)               do {} while(0)
#endif /* CONFIG_DBG_STATS */


#endif