#ifndef RTFL_UTILS_STATUS_H
#define RTFL_UTILS_STATUS_H

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

#ifdef _WIN32
#ifdef RTFL_UTILS_EXPORTS
#define RTFL_UTILS_API __declspec(dllexport)
#else
#define RTFL_UTILS_API __declspec(dllimport)
#endif
#else
#define RTFL_UTILS_API __attribute__((visibility("default")))
#endif

#ifdef __cplusplus
#define RTFL_UTILS_NULL_PTR nullptr
extern "C" {
#else
#define RTFL_UTILS_NULL_PTR NULL
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Статусы, условия статусов выполнения функций библиотеки
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// Статус-коды функций библиотеки.
typedef enum rtfl_utils_StatusCode {
        RTFL_UTILS_ST_OK = 0,             ///< Функция выполнена успешно.
        RTFL_UTILS_ST_INTERNAL_ERROR = 1, ///< Возникла внутренняя ошибка.
        RTFL_UTILS_ST_NULL_PTR_ARG = 2,   ///< В списке переданных аргументов обнаружен нулевой указатель.
        RTFL_UTILS_ST_SYSTEM_ERROR = 3,   ///< Возникла ошибка выполнения системного вызова.
        RTFL_UTILS_ST_NO_CPU_INFO = 4,    ///< Не удалось получить информацию о процессорах.
        RTFL_UTILS_ST_NO_HD_INFO = 5,     ///< Не удалось получить информацию о внутренних жестких дисках.
} rtfl_utils_StatusCode;

///< Коды условий статусов.
typedef enum rtfl_utils_ConditionCode {
        RTFL_UTILS_COND_MESSAGE = 0,   ///< Текстовое сообщение.
        RTFL_UTILS_COND_ERROR_CODE = 1 ///< Код системной ошибки.
} rtfl_utils_ConditionCode;

/// Возвращает текстовое описание статус-кода.
/// \param status - статус-код вызова функции библиотеки.
/// \param outDescr - текстовое описание статус-кода. Если код недействителен, принимает значение RTFL_UTILS_NULL_PTR.
/// \return Код возврата. Возможные значения: #RTFL_UTILS_ST_OK, #RTFL_UTILS_ST_INTERNAL_ERROR.
RTFL_UTILS_API rtfl_utils_StatusCode
rtfl_utils_status_description(rtfl_utils_StatusCode status, const char** outDescr);

/// Возвращает текстовое описание кода условия.
/// \param cond - код условия из функции #rtfl_utils_last_status_conditions.
/// \param outDescr - текстовое описание кода условия. Если код недействителен, принимает значение RTFL_UTILS_NULL_PTR.
/// \return Код возврата. Возможные значения: #RTFL_UTILS_ST_OK, #RTFL_UTILS_ST_INTERNAL_ERROR.
RTFL_UTILS_API rtfl_utils_StatusCode
rtfl_utils_condition_description(rtfl_utils_ConditionCode cond, const char** outDescr);

///< Идентификатор типа полезного значение условия.
typedef enum rtfl_utils_DetailType {
        RTFL_UTILS_DETAIL_int64 = 0,
        RTFL_UTILS_DETAIL_char_ptr = 1
} rtfl_utils_DetailType;

///< Тип полезного значение условия.
typedef union rtfl_utils_DetailValue {
        int64_t num; ///< Целое число.
        char* str;   ///< Строка (ASCII, null-terminated).
} rtfl_utils_DetailValue;

/// Полезное значение условия.
/// Представляет дополнительную информацию условия возникновения ошибки при выполнении функции.
typedef struct rtfl_utils_ConditionDetail {
        rtfl_utils_DetailType type;   ///< Тип значения.
        rtfl_utils_DetailValue value; ///< Значение.
} rtfl_utils_ConditionDetail;


/// Условие статуса выполнения функции.
typedef struct rtfl_utils_StatusCondition {
        rtfl_utils_ConditionCode code;     ///< Код условия.
        rtfl_utils_ConditionDetail detail; ///< Полезное значение условия.
} rtfl_utils_StatusCondition;

/// Возвращает список дополнительных условий последнего статуса выполнения функции.
/// Каждый исполняемый поток имеет свой список.
/// \param outConditions - список условий.
/// \param outCount - размер списка.
/// \return Код возврата. Возможные значения: #RTFL_UTILS_ST_OK, #RTFL_UTILS_ST_INTERNAL_ERROR.
RTFL_UTILS_API rtfl_utils_StatusCode
rtfl_utils_last_status_conditions(rtfl_utils_StatusCondition** outConditions, size_t* outCount);

/// Освобождает память выделенную под список условий в функции #rtfl_utils_last_status_conditions
/// \param conditions - список условий. Должен быть ненулевым.
/// \param amount - размер списка.
/// \return Код возврата. Возможные значения: #RTFL_UTILS_ST_OK, #RTFL_UTILS_ST_INTERNAL_ERROR.
RTFL_UTILS_API rtfl_utils_StatusCode
rtfl_utils_last_status_conditions_destroy(rtfl_utils_StatusCondition** conditions, size_t amount);

#ifdef __cplusplus
}
#endif

#endif // RTFL_UTILS_STATUS_H
