#ifndef RTFLASH_ST_H
#define RTFLASH_ST_H

#include "rtflash-macros.h"

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

#ifdef __cplusplus
extern "C" {
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// \file rtflash-status.h
/// \brief Обработка кодов возврата

/// \enum rtflash_StatusCode
/// \brief Коды возврата функций библиотеки
typedef enum rtflash_StatusCode {
        RTFLASH_ST_OK = 0, ///< Команда выполнена успешно

        // Специальные ошибки
        RTFLASH_ST_INTERNAL_ERROR = 1, ///< Внутренняя ошибка
        RTFLASH_ST_PCSC_ERROR = 2,     ///< Ошибка библиотеки PCSC
        RTFLASH_ST_NULL_PTR_ARG = 3,   ///< Передан нулевой указатель

        // APDU-like ошибки
        RTFLASH_ST_APDU_ERROR = 6000,                      ///< Не используется
        RTFLASH_ST_FILE_NOT_FOUND = 6001,                  ///< Файл не найден
        RTFLASH_ST_INVALID_RIGHTS = 6002,                  ///< Недопустимые права доступа
        RTFLASH_ST_VERIFY_FAILED = 6003,                   ///< Ошибка проверки данных
        RTFLASH_ST_INCORRECT_PARAMETERS = 6004,            ///< Неправильные параметры
        RTFLASH_ST_COMMAND_NOT_SUPPORTED = 6005,           ///< Команда не поддерживается устройством
        RTFLASH_ST_OBJECT_BLOCKED = 6006,                  ///< Указанный объект заблокирован
        RTFLASH_ST_WRONG_DATA_LENGTH = 6007,               ///< Некорректная длина данных
        RTFLASH_ST_NO_SPACE_FOR_RECORD = 6008,             ///< Недостаточно места для добавления записи в файл
        RTFLASH_ST_WRONG_PIN_POLITICS = 6009,              ///< Неправильная политика PIN‑кода
        RTFLASH_ST_PIN_REUSE_ERROR = 6010,                 ///< PIN‑код уже использовался недавно, смена кода невозможна
        RTFLASH_ST_CONDITIONS_OF_USE_NOT_SATISFIED = 6011, ///< Неподходящие условия выполнения команды
        RTFLASH_ST_DOUBLE_LOGIN = 6012,                    ///< Для указанного пользователя аутентификация уже выполнена
        RTFLASH_ST_INVALID_DATA = 6013,                    ///< Некорректные данные
        RTFLASH_ST_NO_FREE_LOCAL_FILE_ID = 6014,           ///< Нет свободных идентификаторов для локальных файлов аутентификации
        RTFLASH_ST_NO_MEMORY = 6015,                       ///< На устройстве недостаточно памяти
        RTFLASH_ST_COMMAND_FAILED = 6016,                  ///< Ошибка выполнения команды
        RTFLASH_ST_DEVICE_BROKEN = 6017,                   ///< Обнаружено нарушение целостности ОС устройства
        RTFLASH_ST_UNSUPPORTED_MODE_OF_COMMAND = 6018,     ///< Режим команды не поддерживается устройством
        RTFLASH_ST_OBJECT_EXISTS = 6019,                   ///< Не используется
        RTFLASH_ST_REFERENCE_DATA_NOT_FOUND = 6020,        ///< Референсные данные не найдены
        RTFLASH_ST_INCORRECT_OBJECT_LIFE_STAGE = 6021,     ///< Команда не допустима на данной стадии (фазе) жизненного цикла файлового объекта/flash-памяти

        // Другие ошибки
        RTFLASH_ST_LOGIC_ERROR = 100000,                   ///< Не используется
        RTFLASH_ST_INVALID_RECORD_COUNT = 100001,          ///< Некорректное количество записей
        RTFLASH_ST_INVALID_RECORD_SIZE = 100002,           ///< Некорректный размер записи
        RTFLASH_ST_INVALID_MVA_SIZE = 100003,              ///< Некорректный размер MVA (max количество записей * max размер записи)
        RTFLASH_ST_INVALID_ATTEMPT_COUNT = 100004,         ///< Некорректное количество попыток доступа
        RTFLASH_ST_CD_ROM_PERMANENT_ONLY = 100005,         ///< Для раздела CD‑ROM доступно только изменение постоянных прав доступа
        RTFLASH_ST_INVALID_SECTION_ID = 100006,            ///< Некорректный идентификатор раздела
        RTFLASH_ST_JOURNAL_READ_ONLY_TEMP = 100007,        ///< Журнал может быть временно переключён только в режим «только чтение»
        RTFLASH_ST_JOURNAL_RO_ENCRYPTED_CONFLICT = 100008, ///< Журнал нельзя переключить в режим «только чтение», если зашифрованный раздел находится в режиме «только чтение» или «чтение‑запись»
        RTFLASH_ST_INVALID_SECTION_COUNT = 100009,         ///< Некорректное количество разделов
        RTFLASH_ST_INVALID_SECTION_SIZE = 100010,          ///< Некорректный размер раздела
        RTFLASH_ST_INVALID_SECTIONS_TOTAL_SIZE = 100011,   ///< Некорректный общий размер разделов
        RTFLASH_ST_JOURNAL_EVENTS_ALREADY_EXISTS = 100012, ///< Раздел журнала событий безопасности уже существует
        RTFLASH_ST_JOURNAL_EVENTS_MISSING = 100013,        ///< Раздел событий журнала отсутствует
        RTFLASH_ST_INVALID_JOURNAL_EVENTS_SIZE = 100014,   ///< Некорректный размер раздела событий журнала
        RTFLASH_ST_INVALID_JOURNAL_ACCESS_RIGHTS = 100015, ///< Некорректные права доступа к разделу журнала
        RTFLASH_ST_UNSUPPORTED_SECTION_TYPE = 100016,      ///< Указанный тип раздела не поддерживается устройством
        RTFLASH_ST_INVALID_PROTECT_CONDITIONS = 100017,    ///< Некорректная комбинация условий защиты
        RTFLASH_ST_INVALID_SECRET_ID = 100018,             ///< Некорректный идентификатор секрета
        RTFLASH_ST_RECORD_MISMATCH = 100019,               ///< Переданная запись не соответствует ни одной из записей в указанном MVA
        RTFLASH_ST_INCORRECT_LOGIN = 100021,               ///< Неправильный логин
        RTFLASH_ST_DEVICE_NOT_FOUND = 100022,              ///< Устройство с указанным серийным номером не найдено
        RTFLASH_ST_RECORD_NOT_FOUND = 100023,              ///< Не удалось найти запись с указанным идентификатором
        RTFLASH_ST_UNEXPECTED_APDU_RESPONSE = 100024,      ///< Неверный APDU‑ответ от устройства
        RTFLASH_ST_INVALID_STRING_SIZE = 100025,           ///< Некорректный размер строки
        RTFLASH_ST_JOURNAL_READ_ONLY_FORBIDDEN = 100026,   ///< Журнальный раздел нельзя создать с запрещённым временным переключением в режим «только чтение»
        RTFLASH_ST_OBJECT_ID_TYPE_MISMATCH = 100027,       ///< Тип объекта, переданный по идентификатору, не соответствует ожидаемому
        RTFLASH_ST_INVALID_PIN_SIZE = 100028,              ///< Некорректный размер PIN-кода
        RTFLASH_ST_INVALID_SECRET_TYPE = 100029,           ///< Некорректный тип секрета
} rtflash_StatusCode;

/// Коды условий
typedef enum rtflash_ConditionCode {
        RTFLASH_COND_STD_EXCEPTION = 0,             ///< Исключение стандартной библиотеки
        RTFLASH_COND_APDU_STATUS = 1,               ///< Статус APDU‑команды
        RTFLASH_COND_EXCEPTION_LOCATION = 2,        ///< Местоположение исключения
        RTFLASH_COND_PCSC_ERROR_CODE = 3,           ///< Код ошибки PCSC
        RTFLASH_COND_PCSC_ERROR_STRING = 4,         ///< Код ошибки PCSC в шестнадцатеричном виде
        RTFLASH_COND_REMAINING_LOGIN_ATTEMPTS = 5,  ///< Оставшееся количество попыток входа
        RTFLASH_COND_TLV_PARSE_FAIL = 6,            ///< Ошибка разбора структуры TLV
        RTFLASH_COND_APDU_RESPONSE = 7,             ///< APDU‑ответ от устройства
        RTFLASH_COND_PROTECT_CONDS_BYTE = 8,        ///< Байт условий защиты
        RTFLASH_COND_CURRENT_MAX_SECTION_COUNT = 9, ///< Максимальное количество разделов, которое может быть создано в текущем состоянии раздела памяти
        RTFLASH_COND_AVAILABLE_FLASH_SIZE = 10,     ///< Доступный объём flash‑памяти
        RTFLASH_COND_SECTION_SIZE = 11,             ///< Размер раздела
        RTFLASH_COND_SECTION_TYPE = 12,             ///< Тип раздела
        RTFLASH_COND_SECRET_ID = 13,                ///< Идентификатор секрета
        RTFLASH_COND_SECRET_ID_VALID_RANGE = 14,    ///< Допустимый диапазон значений идентификатора секрета
        RTFLASH_COND_EXPECTED_SECRET_TYPE = 15      ///< Ожидаемый тип секрета
} rtflash_ConditionCode;

/// Идентификатор типа информации условия
typedef enum rtflash_DetailType {
        RTFLASH_DETAIL_int64 = 0,   ///< Тип int64
        RTFLASH_DETAIL_char_ptr = 1 ///< Тип Си строка
} rtflash_DetailType;

/// Тип информации условия
typedef union rtflash_DetailValue {
        int64_t num;
        char* str; ///< ASCII, null-terminated
} rtflash_DetailValue;

/// \brief Представляет тип хранимой дополнительной информации
typedef struct rtflash_ConditionDetail {
        rtflash_DetailType type;
        rtflash_DetailValue value;
} rtflash_ConditionDetail;

/// \brief Представляет дополнительную информацию, которая может быть получена в случае возникновения ошибки при выполнении функции.
typedef struct rtflash_StatusCondition {
        rtflash_ConditionCode code;
        rtflash_ConditionDetail detail;
} rtflash_StatusCondition;

/// Возвращает список дополнительных условий _последнего_ статуса выполнения функции библиотеки.
/// \note Каждый исполняемый поток имеет свой список.
/// \note При успешном выполнении функции #rtflash_last_status_conditions необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_last_status_conditions_destroy. При неуспешном выполнении очистка не требуется.
/// \attention выполнение функции не устанавливает последний статус.
/// \param outConditions - список условий.
/// \param outCount - размер списка.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode
rtflash_last_status_conditions(rtflash_StatusCondition** outConditions, size_t* outCount);

/// Освобождает память выделенную под список условий в функции #rtflash_last_status_conditions
/// \param conditions - список условий.
/// \param amount - размер списка.
RTFLASH_API void
rtflash_last_status_conditions_destroy(rtflash_StatusCondition** conditions, size_t amount);

/// Возвращает текстовое описание статус-кода.
/// \attention Не устанавливает последний статус выполнения функции библиотеки.
/// \param status - статус-код, возвращаемый вызовом любой функции библиотеки.
/// \param outDescr - текстовое описание статус-кода. Если код недействителен, принимает значение RTFLASH_NULL_PTR.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode
rtflash_status_description(rtflash_StatusCode status, const char** outDescr);

/// Возвращает текстовое описание кода условия.
/// \attention Не устанавливает последний статус выполнения функции библиотеки.
/// \param cond - код условия из функции #rtflash_last_status_conditions.
/// \param outDescr - текстовое описание кода условия. Если код недействителен, принимает значение RTFLASH_NULL_PTR.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode
rtflash_condition_description(rtflash_ConditionCode cond, const char** outDescr);

#ifdef __cplusplus
}
#endif

#endif // RTFLASH_ST_H
