#ifndef RTFLASH_H
#define RTFLASH_H

/// \file rtflash.h
/// \brief Функции библиотеки

#include "rtflash-macros.h"
#include "rtflash-status.h"
#include "rtflash-types.h"

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Базовые операции

/// Возвращает список, содержащий серийные номера всех подключенных в данный момент устройств Рутокен ЭЦП (далее -- токенов).
/// \note При успешном выполнении функции #rtflash_create_token_list необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_destroy_token_list. При неуспешном выполнении очистка не требуется.
/// \param outTokens - указатель на список серийных номеров. Должен быть ненулевым.
/// \param outTokenCount - указатель на размер списка. Должен быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_create_token_list(rtflash_TokenSerial** outTokens, size_t* outTokenCount);

/// Удаляет список подключенных на данный момент токенов, полученный  с помощью функции #rtflash_create_token_list.
/// \param tokens - указатель на список серийных номеров.
RTFLASH_API void rtflash_destroy_token_list(rtflash_TokenSerial** tokens);

/// Создает программный объект-обертку для работы с конкретным токеном.
/// \note При успешном выполнении функции #rtflash_create_token необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_destroy_token. При неуспешном выполнении очистка не требуется.
/// \param tokenSerial - серийный номер целевого токена.
/// \param outToken - инициализированный объект-обертка для токена.
///
/// После использования программный объект-обертку необходимо удалить с помощью функции #rtflash_destroy_token.
RTFLASH_API rtflash_StatusCode rtflash_create_token(rtflash_TokenSerial tokenSerial, rtflash_Token* outToken);

/// Удаляет программный объект-обертку для работы с конкретным токеном, созданный с помощью функции #rtflash_create_token.
/// Автоматически вызывает функцию #rtflash_logout.
/// \param token - указатель на удаляемый объект-обертку токена.
RTFLASH_API void rtflash_destroy_token(rtflash_Token* token);

/// Определяет, поддерживается ли токен библиотекой rtflash.
/// \param token - проверяемый токен.
/// \param outIsSupported - указатель на логическую переменную, в которой сохраняется результат проверки.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_is_token_supported(rtflash_Token token, bool* outIsSupported);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Login / Logout

/// Выполняет аутентификацию владельца токена по PIN-коду Пользователя.
/// \note Для сброса прав, полученных после успешной аутентификации, необходимо вызвать функцию #rtflash_logout.
/// \note Количество оставшихся попыток аутентификации передается через механизм условий статуса.
/// Условие #RTFLASH_COND_REMAINING_LOGIN_ATTEMPTS можно получить через вызов функции #rtflash_last_status_conditions
/// после неуспешной аутентификации.
/// \param token - указатель на токен для аутентификации. Должен быть ненулевым.
/// \param pin - PIN-код Пользователя. Размер PIN-кода должен быть в пределах [1,RTFLASH_PIN_MAX_SIZE] байт.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_login_user(rtflash_Token token, const rtflash_PinCode pin);

/// Выполняет аутентификацию владельца токена по PIN-коду Администратора.
/// \note Для сброса прав, полученных после успешной аутентификации, необходимо вызвать функцию #rtflash_logout.
/// \note Количество оставшихся попыток аутентификации передается через механизм условий статуса.
/// Условие #RTFLASH_COND_REMAINING_LOGIN_ATTEMPTS можно получить через вызов функции #rtflash_last_status_conditions
/// после неуспешной аутентификации.
/// \param token - указатель на токен для аутентификации. Должен быть ненулевым.
/// \param pin - PIN-код Администратора. Размер PIN-кода должен быть в пределах [1,RTFLASH_PIN_MAX_SIZE] байт.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_login_admin(rtflash_Token token, const rtflash_PinCode pin);

/// Выполняет аутентификацию владельца токена по записи из многозначного аутентификатора (MVA).
/// \note Для сброса прав, полученных после успешной аутентификации, необходимо вызвать функцию #rtflash_logout.
/// \note Количество оставшихся попыток аутентификации передается через механизм условий статуса.
/// Условие #RTFLASH_COND_REMAINING_LOGIN_ATTEMPTS можно получить через вызов функции #rtflash_last_status_conditions
/// после неуспешной аутентификации.
/// \param token - указатель на токен для аутентификации. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA, с записью из которого проводится сравнение.
/// \param record - байтовая последовательность для сверки.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_login_mva(rtflash_Token token,
                                                 rtflash_MvaId mvaId,
                                                 rtflash_MvaRecord record);

/// Выполняет аутентификацию владельца токена по локальному PIN-коду.
/// \note Одновременная аутентификация по нескольким локальным PIN-кодам не поддерживается.
/// \note Для сброса прав, полученных после успешной аутентификации, необходимо вызвать функцию #rtflash_logout.
/// \note Количество оставшихся попыток аутентификации передается через механизм условий статуса.
/// Условие #RTFLASH_COND_REMAINING_LOGIN_ATTEMPTS можно получить через вызов функции #rtflash_last_status_conditions
/// после неуспешной аутентификации.
/// \param token - указатель на токен для аутентификации. Должен быть ненулевым.
/// \param localPinId - идентификатор локального PIN-кода.
/// \param localPin - локальный PIN-код.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_login_local_pin(rtflash_Token token,
                                                       rtflash_LocalPinId localPinId,
                                                       rtflash_PinCode localPin);

/// Сбрасывает права владельца токена, полученные после его успешной аутентификации.
/// \param token - указатель на токен для сброса прав. Должен быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_logout(rtflash_Token token);

/// Сбрасывает счетчик неуспешных попыток аутентификации по PIN-коду Пользователя до значения по умолчанию.
/// \attention Требуются права администратора.
/// \param token - указатель на токен для сброса PIN-кода Пользователя. Должен быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_reset_login_attempts_user(rtflash_Token token);

/// Сбрасывает счетчик неуспешных попыток аутентификации по локальному PIN-коду до значения по умолчанию.
/// \attention Требуются права администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param localPinId - идентификатор локального PIN-кода.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_reset_login_attempts_local_pin(rtflash_Token token,
                                                                      rtflash_LocalPinId localPinId);

/// Сбрасывает счетчик неуспешных попыток аутентификации по MVA до значения, заданного при создании MVA.
/// \attention Требуются права администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_reset_login_attempts_mva(rtflash_Token token, rtflash_MvaId mvaId);

/// Получает количество оставшихся попыток аутентификации по PIN-коду Пользователя.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param outAttemptsLeft - указатель на числовую переменную, в которой хранится количество оставшихся попыток аутентификации.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_get_remaining_login_attempts_user(rtflash_Token token,
                                                                         rtflash_Attempts* outAttemptsLeft);

/// Получает количество оставшихся попыток аутентификации по PIN-коду Администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param outAttemptsLeft - указатель на числовую переменную, в которой хранится количество оставшихся попыток аутентификации.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_get_remaining_login_attempts_admin(rtflash_Token token,
                                                                          rtflash_Attempts* outAttemptsLeft);

/// Получает количество оставшихся попыток аутентификации по записи из MVA.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA, с записью из которого проводится сравнение.
/// \param outAttemptsLeft - указатель на числовую переменную, в которой хранится количество оставшихся попыток аутентификации.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_get_remaining_login_attempts_mva(rtflash_Token token,
                                                                        rtflash_MvaId mvaId,
                                                                        rtflash_Attempts* outAttemptsLeft);

/// Получает количество оставшихся попыток аутентификации по локальному PIN-коду.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param localPinId - идентификатор локального PIN-кода.
/// \param outAttemptsLeft - указатель на числовую переменную, в которой хранится количество оставшихся попыток аутентификации.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_get_remaining_login_attempts_local_pin(rtflash_Token token,
                                                                              rtflash_LocalPinId localPinId,
                                                                              rtflash_Attempts* outAttemptsLeft);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Работа с flash-разделами

/// Возвращает список разделов flash-памяти токена.
/// \note При успешном выполнении функции #rtflash_create_section_list необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_destroy_section_list. При неуспешном выполнении очистка не требуется.
/// \param token - указатель на токен, информацию о flash-памяти которого необходимо получить. Должен быть ненулевым.
/// \param outSections - указатель на список разделов. Должен быть ненулевым.
/// \param outSectionCount - указатель на количество разделов. Должно быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_create_section_list(rtflash_Token token,
                                                           rtflash_Section** outSections,
                                                           size_t* outSectionCount);

/// Удаляет список разделов, полученных с помощью функции #rtflash_create_section_list.
/// \param sections - указатель на список разделов для удаления.
RTFLASH_API void rtflash_destroy_section_list(rtflash_Section** sections);

/// Возвращает доступный для форматирования размер flash-памяти в мегабайтах.
/// \param token - указатель на токен, для которого нужно получить информацию. Должен быть ненулевым.
/// \param outSize - доступный для форматирования размер flash-памяти.
///                  Не включает размеры журнальных разделов: журнала СБ и журнала ФО.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_get_available_flash_size(rtflash_Token token, rtflash_MemSizeMB* outSize);

/// Разбивает flash-память токена на разделы.
/// \attention Требуются права администратора.
/// \param token - указатель на токен для выполнения операции. Должен быть ненулевым.
/// \param sections - список разделов.
///                   Поле id секции игнорируется.
///                   Суммарный размер разделов не должен превышать доступного для форматирования размера из функции #rtflash_get_available_flash_size.
///                   Минимальное количество разделов составляет 1.
///                   Максимальное количество новых разделов составляет 8 - 1 (если есть журнал ФО) - 1 (если есть журнал СБ) - 1 (если есть зашифрованный раздел).
///                   Журнальный (СБ и ФО) и зашифрованный разделы можно создать только один раз.
///                   Журнальный (СБ и ФО) и зашифрованный разделы можно создать только с правами доступа Hidden.
///                   Журнал ФО поддерживается только для Rutoken ECP 3.0 Flash 5900.
///                   Размер журнала ФО должен быть >= 500 Мб, но не более половины всей flash-памяти.
///                   Размер журнала СБ должен быть >= 500 Мб.
///                   Зашифрованный раздел поддерживается только для Rutoken ECP 3.0 Flash 5900.
///                   Операции с зашифрованным разделом должны быть защищены с помощью пользовательского PIN-кода или локального PIN-кода в качестве единственного или одного из атрибутов безопасности.
///                   Размер зашифрованного раздела должен быть менее половины всей flash-памяти токена.
/// \param sectionCount - количество разделов.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_split_into_sections(rtflash_Token token,
                                                           rtflash_Section const* sections,
                                                           size_t sectionCount);

/// Изменяет права доступа к разделу.
/// \attention Требуются права владельца, идентификатор которого был выставлен для данного раздела при разметке.
/// \note Временный перевод атрибута доступа раздела в 'hidden' не требует никаких прав доступа, т.е. эта операция по умолчанию разрешена.
/// \param token - указатель на токен для выполнения операции. Должен быть ненулевым.
/// \param sectionId - идентификатор раздела для изменения прав.
/// \param accessRights - новые права доступа к разделу.
///                       Изменение прав доступа на CD-ROM могут быть только постоянными.
///                       Журнальный раздел может быть установлен только в состояние RO и только временно.
///                       Журнальный раздел не может быть установлен в состояние RO, если зашифрованный раздел находится в состоянии RO или RW.
/// \param isPermanent - false, если изменение должно быть отменено после выхода из системы или отключения токена.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_change_section_access_rights(rtflash_Token token,
                                                                    rtflash_SectionId sectionId,
                                                                    rtflash_SectionAccessState accessRights,
                                                                    bool isPermanent);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Работа с MVA

/// Возвращает список идентификаторов MVA, присутствующих на токене в данный момент.
/// \note При успешном выполнении функции #rtflash_create_mva_id_list необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_destroy_mva_id_list. При неуспешном выполнении очистка не требуется.
/// \param token - указатель на токен, MVA которого нужно получить. Должен быть ненулевым.
/// \param outIds - указатель на список идентификаторов MVA. Должен быть ненулевым.
/// \param outCount - указатель на количество MVA. Должен быть ненулевым.
RTFLASH_API rtflash_StatusCode rtflash_create_mva_id_list(rtflash_Token token, rtflash_MvaId** outIds, size_t* outCount);

/// Удаляет список идентификаторов MVA, полученный с помощью функции #rtflash_create_mva_id_list.
/// \param mvaIds - указатель на список идентификаторов MVA для удаления.
RTFLASH_API void rtflash_destroy_mva_id_list(rtflash_MvaId** mvaIds);

/// Создает новый MVA на токене.
/// Созданный MVA можно удалить только с помощью форматирования токена.
/// Использование MVA для аутентификации (#rtflash_login_mva) не требует каких-либо прав.
/// \attention Количество секретов (см. #rtflash_Secret) на токене не должно превышать #RTFLASH_SECRET_MAX_COUNT.
/// \attention Требуются права администратора.
/// \param token - указатель на токен для создания MVA. Должен быть ненулевым.
/// \param params - параметры MVA для создания. Должны быть ненулевыми.
/// \param outMvaId - указатель на идентификатор созданного MVA. Должен быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_create_mva(rtflash_Token token,
                                                  rtflash_MvaParams const* params,
                                                  rtflash_MvaId* outMvaId);

/// Добавляет запись в MVA в качестве аутентификатора.
/// \attention Требуются права администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA, в который нужно добавить запись.
/// \param record - запись. Размер записи должен быть в пределах [1, RTFLASH_MVA_MAX_RECORD_SIZE].
///                 Будет записана байтовая последовательность до первого символа '/0' или длиной RTFLASH_MVA_MAX_RECORD_SIZE.
/// \param outRecordId - идентификатор добавленной записи.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_mva_add_record(rtflash_Token token,
                                                      rtflash_MvaId mvaId,
                                                      rtflash_MvaRecord record,
                                                      rtflash_RecordId* outRecordId);

/// Удаляет запись из MVA.
/// \attention Требуются права администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA, из которого нужно удалить запись.
/// \param recordId - идентификатор записи для удаления. Нумерация идентификаторов записей начинается с 1.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_mva_delete_record(rtflash_Token token,
                                                         rtflash_MvaId mvaId,
                                                         rtflash_RecordId recordId);

/// Удаляет все записи из MVA.
/// \attention Требуются права администратора.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param mvaId - идентификатор MVA.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_mva_clear_all_records(rtflash_Token token, rtflash_MvaId mvaId);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Работа с локальными PIN-кодами

/// Возвращает список локальных PIN-кодов, присутствующих на токене в данный момент.
/// \note При успешном выполнении функции #rtflash_create_local_pin_id_list необходимо выполнить очистку выделенной памяти с
/// помощью функции #rtflash_destroy_local_pin_id_list. При неуспешном выполнении очистка не требуется.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param outIds - указатель на список. Должен быть ненулевым.
/// \param outCount - указатель на количество. Должен быть ненулевым.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_create_local_pin_id_list(rtflash_Token token,
                                                                rtflash_LocalPinId** outIds,
                                                                size_t* outCount);

/// Удаляет список локальных PIN-кодов, полученный с помощью функции #rtflash_create_local_pin_id_list.
/// \param ids - указатель на список для удаления.
RTFLASH_API void rtflash_destroy_local_pin_id_list(rtflash_LocalPinId** ids);

/// Создает локальный PIN-код на токене.
/// \attention Требуются права пользователя или администратора.
/// \attention Количество секретов (#rtflash_Secret) на токене не должно превышать #RTFLASH_SECRET_MAX_COUNT.
/// \note Максимальное число последующих неуспешных попыток аутентификации по локальному PIN-коду - #RTFLASH_MAX_LOGIN_ATTEMPT_COUNT.
/// Превышение указанного числа приведет к блокировке объекта. Для разблокировки необходимо воспользоваться функцией #rtflash_reset_login_attempts_local_pin.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param localPin - устанавливаемый локальный PIN-код. Длина PIN-кода должна находиться в пределах [RTFLASH_LOCAL_PIN_MIN_SIZE, RTFLASH_LOCAL_PIN_MAX_SIZE] символов.
/// \param secureType - тип защиты от изменений локального PIN-кода. При установке типа RTFLASH_SECURE_T_LOCAL_PIN, защита локального PIN-кода происходит на самого себя.
/// Параметр может принимать одно из трех значений: RTFLASH_SECURE_T_LOCAL_PIN, RTFLASH_SECURE_T_ADMIN или RTFLASH_SECURE_T_USER;
/// \param outLocalId - выходной идентификатор созданного локального PIN-кода.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_create_local_pin(rtflash_Token token,
                                                        rtflash_PinCode localPin,
                                                        rtflash_SecureType secureType,
                                                        rtflash_LocalPinId* outLocalId);

/// Изменяет локальный PIN-код на новый.
/// \attention Требуются права доступа заданные при создании локального PIN-кода функцией #rtflash_create_local_pin.
/// \attention Статус прав (Login / Logout) по данному локальному PIN-коду сохраняется при изменении значения.
/// \param token - указатель на токен. Должен быть ненулевым.
/// \param localId - идентификатор локального PIN-кода. Должен идентифицировать существующий локальный PIN-код.
/// \param newLocalPin - новый локальный PIN-код. Длина PIN-кода должна находиться в пределах [RTFLASH_LOCAL_PIN_MIN_SIZE, RTFLASH_LOCAL_PIN_MAX_SIZE] символов.
/// \return Код возврата.
RTFLASH_API rtflash_StatusCode rtflash_change_local_pin(rtflash_Token token,
                                                        rtflash_LocalPinId localId,
                                                        rtflash_PinCode newLocalPin);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Другие функции

/// Записывает информацию о ПК в журнал СБ токена.
/// \param token - токен, на который записывается информация. Должен быть ненулевым.
/// \param pcInfo - информация о ПК для записи. Должна быть ненулевой.
RTFLASH_API rtflash_StatusCode rtflash_add_pc_info_to_journal(rtflash_Token token, rtflash_PcInfo const* pcInfo);

#ifdef __cplusplus
}
#endif

#endif // RTFLASH_H
