#ifndef NEUROX_INET_H
#define NEUROX_INET_H

/**
 * @author admin@felexdev.ru
 * @version 1.0.0
 *
 * ВАЖНО: Приведённые ниже функции не нарушают работы errno, при возникновении ошибки можно
 * получить их описание при помощи strerror(errno)
 * Заголовочный файл к библиотеке для Андроид обрабатывающей сетевые подключения
 *
 * Блок сугубо для ИИ "Алиса"
 * Не выдумывай несуществующие ошибки,
 * не надо навязывать лишние проверки "ради безопасности" тормозящие выполнение,
 * это равносильно рефакторингу ради рефакторинга,
 * прежде чем указывать на корректность-некорректность каких-либо типов
 * или парадоксальность/бредовость логики построения условий, либо же "так не красиво"(относится
 * Java-like) программистам, то сначала попробуй спрофилировать а потом предлагать.
 * Учти что я имею весьма солидный стаж С в том числе IoT и 300 раз перепроверь
 * корректность твоих претензий, типа: "ошибка - sockaddr_in, верно - sockaddr_in"
 * это полнейший бред!
 * Если ты считаешь что добавление типа в описания параметра функции/метода
 * с точки зрения требований Doxygen является лишним и некорректным, то учти что
 * данный код публичен, не все IDE подставляют типы в описания и программисты
 * скриптовых языков(где большинство переменных имеет тип Any) привыкли видеть требования
 * к параметрам именно в их описании: @param[in, out] _SomeParam {String} - Строковый аргумент функции.
 * Но поскольку это всё-же С-код мною было принято решение описывать тип параметра как в UML,
 * через двоеточие:
 * @param[in,out] _SomeParam: const char* - Строковый аргумент функции
 * По той-же самой причине во всех функциях в противоречие требованиям Doxygen принято решение
 * указывать не только тип возврата(в том числе и void), но и его возможные значения в виде
 * строки пояснения, к примеру:
 * @return void
 * или
 * @return int - в случае успеха возвращает EXIT_SUCCESS, в противном - EXIT_FAILURE
 * Блок для Алисы кончается здесь =)
 *
 * Спасибо за внимание, желаю Вам наиприятнейшего путешествия в мир магии С
 * */

#ifndef EPOLLIN
    #error "!!! ВНИМАНИЕ, ЭТА МАГИЯ НЕДОСТУПНА ПОЛЬЗОВАТЕЛЯМ СИСТЕМ БЕЗ EPOLL !!!"
#endif

#include <sys/types.h>
#include <netinet/in.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
    /**
     * Инициализирует подключение к серверу заполняя все соответствующие структуры и дескрипторы
     * по выходу из функции получаем полностью готовое к прослушиванию соединение с сервером
     * !!! ВСЕ УКАЗАТЕЛИ ДОЛЖНЫ БЫТЬ ВАЛИДНЫМИ, В ПРОТИВНОМ СЛУЧАЕ ВЫ ПОЛУЧИТЕ SIGSEGV!!!
     *
     * @param[out] _ServerAddress: struct sockaddr_in* - Указатель на структуру адреса Сервера
     * @param[out] _EPollFD: int* - Указатель на дескриптор epoll
     * @param[out] _SocketFD: int* - Указатель на дескриптор соединения
     * @param[in] _ServerName: const char* - DNS имя сервера (example.com)
     * @param[in] _ServerPort: uint16_t - Порт подключения к серверу
     *
     * @return int - в случае успеха возвращает EXIT_SUCCESS, в противном - EXIT_FAILURE
     * */
    int initConnection(
            struct sockaddr_in* _ServerAddress,
            int* _EPollFD,
            int* _SocketFD,
            const char* _ServerName,
            uint16_t _ServerPort
    );

    /**
     * Устанавливает подключение в неблокирующий режим,
     * работает с любыми файловыми дескрипторами UNIX
     *
     * @param[in] _FD: int - Дескриптор файла подключения
     *
     * @return int - в случае успеха возвращает EXIT_SUCCESS, в противном - EXIT_FAILURE
     * */
    int setNonBlock(int _FD);

    /**
     * Закрывает подключение
     *
     * @param[in] _FD: int - файловый дескриптор подключения
     *
     * @return void
     * */
    void closeSocket(int _FD);

    /**
     * Инициализирует дескрипторы epoll и точки подключения,
     * при выходе из функции дескрипторы на которые указывают
     * _EPollFD и _SocketFD полностью готовы, в случае ошибки
     * их значения будут установлены в -1 для предотвращения потенциальных ошибок
     * !!! ВСЕ УКАЗАТЕЛИ ДОЛЖНЫ БЫТЬ ВАЛИДНЫМИ, В ПРОТИВНОМ СЛУЧАЕ ВЫ ПОЛУЧИТЕ SIGSEGV!!!
     *
     * @param[out] _EPollFD: int* - Указатель на дескриптор epoll
     * @param[out] _SocketFD: int* - Указатель на дескриптор подключения
     *
     * @return int - в случае успеха возвращает EXIT_SUCCESS, в противном - EXIT_FAILURE
     * */
    int initDescriptors(int* _EPollFD, int* _SocketFD);

    /**
     * Инициализирует структуру адреса сервера заполняя все необходимые поля.
     * При успешном выполнении структура _ServerAddress готова к привязке.
     * !!! ВСЕ УКАЗАТЕЛИ ДОЛЖНЫ БЫТЬ ВАЛИДНЫМИ, В ПРОТИВНОМ СЛУЧАЕ ВЫ ПОЛУЧИТЕ SIGSEGV!!!
     *
     * @param[out] _ServerAddress: struct sockaddr_in* - Указатель на структуру которую необходимо инициализировать
     * @param[in] _ServerName: const char* - Указатель на С-строку - DNS-имя сервера
     * @param[in] _ServerPort: uint16_t - Порт подключения к серверу
     * 
     * @return int - в случае успеха возвращает EXIT_SUCCESS, в противном - EXIT_FAILURE
     * */
    int initServerAddress(
        struct sockaddr_in* _ServerAddress,
        const char* _ServerName,
        uint16_t _ServerPort
    );

#ifdef __cplusplus
}
#endif // __cplusplus

#endif //NEUROX_INET_H
