#ifndef UBL_UTILS
#define UBL_UTILS
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <locale.h>
#include <time.h>

#define DesktopPath "/usr/share/applications/"


/**for_dictionaries(element, stack)
 * [EN]
 * 
 * [RU]
 * Работает как for, но нужен для перечисления элементов словаря типа dictioary [stack]. Каждый цикл текущий элемент попадает в [element]
*/
#define for_dictionaries(element, stack) for (element = stack->first; element != NULL; element = element->next)

#define new(type) malloc(sizeof(type))
#define new_arr(type,size) malloc(sizeof(type)*size)

#define get_home_dir_command yon_char_unite("getent passwd \"",yon_ubl_root_user_get(),"\" | cut -d: -f6",NULL)

#define yon_va_while(list,type,target) while ((target=va_arg(list,type)))

typedef enum
{
    DICTIONARY_GTK_WIDGETS_TYPE,
    DICTIONARY_OTHER_TYPE=0,
    DICTIONARY_CHAR_TYPE,
    DICTIONARY_INT_TYPE,
    DICTIONARY_BOOL_TYPE,

} DICT_TYPE;

#define dictionary_fields(type_name) char *key;\
    void *data;\
    struct type_name *next;\
    struct type_name *prev;\
    struct type_name *first;\
    DICT_TYPE data_type;
/**
 * Структура именованого списка.
 * [key] - ключ элемента
 * [data] - хранимое значение
 * [next] - следующий элемент списка
 * [prev] - предыдущий элемент списка
 * [first] - первый элемент списка 
 * [data_type] - Тип значения в словаре 
*/
typedef struct dictionary
{
    char *key;
    void *data;
    struct dictionary *next;
    struct dictionary *prev;
    struct dictionary *first;
    DICT_TYPE data_type;
} dictionary;




typedef struct apps
{
    char *Name;
    int Type;
    char *Categories;
    char *Exec;
    char *Icon;
    int Pluggable;
    int DualPluggable;
} apps;

typedef char** config_str;

/**config(key)
 * Возвращает элемент конфигурации ubconfig с ключом [key] или NULL если такого нет
*/
#define config(key) yon_config_get_by_key(key) 

#define yon_remalloc(pointer, size) (!pointer) ? malloc(size) : realloc(pointer, size)
// dictionary functions

/**yon_dictionary_get_data(dictionary, type)
 * [EN]
 * Gets data from dictionary.
 * [dictionary] is dictionary, from which data should be extracted;
 * [type] is type of data, [dictionary] contains.
 * [RU]
 * Возвращает данные из словаря.
 * [dictionary] - словарь из которого достаются данные.
 * [type] - тип данных, хранящихся в словаре [dictionary].
*/
#define yon_dictionary_get_data(dictionary, type) ((type)dictionary->data)

/**yon_dictionary_add_or_create_if_exists_with_data(dict,key,data)
 * [EN]
 * 
 * [RU]
 * Добавляет элемент словаря в конец словаря [dict] c ключом [key] и данными [data].
 * Если словарь не существует, создаёт его 
*/
#define yon_dictionary_add_or_create_if_exists_with_data(dict,key,data) {if (!dict) dict=yon_dictionary_new_with_data(key,data); \
                                                                        else dict=yon_dictionary_append_with_data(dict,key,data);}

/**yon_dictionary_new():
 * [EN]
 * Creates and returns empty dictionary
 * [RU]
 * Создаёт и возвращает пустой словарь.
 */
dictionary *yon_dictionary_new();

/**yon_dictionary_copy(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Создаёт и возвращает копию элемента словаря [dict]
*/
dictionary *yon_dictinoary_copy(dictionary *dict);

/**yon_dictionary_copy_deep(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Создаёт полную копию словаря [dict] и возвращает первый элемент
*/
dictionary *yon_dictionary_copy_deep(dictionary *dict);

/**int yon_dictionary_set_data(dictionary *dict, void *data)
 * [EN]
 * 
 * [RU]
 * Установить элементу словаря [dict] значение [data]
*/
int yon_dictionary_set_data(dictionary *dict, void *data);

/**int yon_dictionary_set_key(dictionary *dict, char *key)
 * [EN]
 * 
 * [RU]
 * Изменяет ключ элемента словаря [dict] на [key]
*/
int yon_dictionary_set_key(dictionary *dict, char *key);

/** int yon_dictionary_set(dictionary *dict, char *key, void *data)
 * [EN]
 * 
 * [RU]
* Устанавливает значение ключа элемента словаря [dict] на [key] и его данные на [data] 
*/
int yon_dictionary_set(dictionary *dict, char *key, void *data);

/**int yon_dictionary_empty(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Очищает элемент словаря [dict] от данных
*/
int yon_dictionary_empty(dictionary *dict);

/**yon_dictionary_switch_to_last(dictionary **dict)
 * [EN]
 * 
 * [RU]
 * Переключает словарь [dict] на последний элемент.
*/
void yon_dictionary_switch_to_last(dictionary **dict);

/**yon_dictionary_create_conneced(dictionary *targetdict)
 * [EN]
 * 
 * [RU]
 * Создаёт новый элемент словаря [targetdict]
*/
dictionary *yon_dictionary_append(dictionary *targetdict);

/**yon_dictionary_get_last(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Возвращает последний элемент словаря [dict].
 * В отличае от yon_dictionary_switch_to_last()
 * словарь [dict] остаётся на прежнем элементе.
*/
dictionary *yon_dictionary_get_last(dictionary *dict);

/**yon_dictionary_switch_places(dictionary *dict, int aim)
 * [EN]
 * 
 * [RU]
 * Меняет элемент словаря [dict] местами с другим элементом.
 * если [aim]<0 элемент меняется местами с левым элементом;
 * если [aim]>0 элемент меняется местами с правым элементом;
*/
dictionary *yon_dictionary_swap(dictionary *dict, int aim);

/**yon_dictionary_make_first(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Устанавливает указатель первого элемента словаря [dict]
 * на текущий элемент. Не использовать.
*/
void yon_dictionary_make_first(dictionary *dict);

/**yon_dictionary_make_nth(dictionary *dict, int nth)
 * [EN]
 * 
 * [RU]
 * Перемещает элемент словаря [dict] на позицию [nth].
*/
void yon_dictionary_make_nth(dictionary *dict, int nth);

/**yon_dictionary_create_with_data(char *key, void *data)
 * [EN]
 * 
 * [RU]
 * Создаёт новый словарь с ключом [key] и указателем на данные [data] 
*/
dictionary *yon_dictionary_new_with_data(char *key, void *data);

/**yon_dictionary_create_with_data_connected(dictionary *dict, char *key, void *data)
 * [EN]
 * 
 * [RU]
 * Создаёт новый элемент словаря, присоединяемый в конец словаря [dict]
 * с ключом [key] и указателем на данные [data]
*/
dictionary *yon_dictionary_append_with_data(dictionary *dict, char *key, void *data);

/**yon_dictionary_connect(dictionary *old, dictionary *toconnect)
 * [EN]
 * 
 * [RU]
 * Присоединяет словарь [toconnect] в конец словаря [old].
*/
dictionary *yon_dictionary_connect(dictionary *old, dictionary *toconnect);

dictionary *yon_dictionary_merge(dictionary *dict1,dictionary *dict2);

/**yon_dictionary_get(dictionary **dict, char *key)
 * [EN]
 * 
 * [RU]
 * Возвращает элемент словаря [dict] с ключом [key].
 * Если такого элемента не было обнаружено, возвращается NULL 
*/
dictionary *yon_dictionary_get(dictionary **dict, char *key);

/**yon_dictionary_rip(dictionary *dict)
 * [EN]
 * 
 * [RU]
 * Вырезает элемент из словаря и возвращает вырезанный элемент.
*/
dictionary *yon_dictionary_rip(dictionary *dict);

/**yon_dictionary_get_nth(dictionary *dict, int place)
 * [EN]
 * 
 * [RU]
 * Возвращает [place]-й элемент словаря [dict]
*/
dictionary *yon_dictionary_get_nth(dictionary *dict, int place);

/** void *yon_dictionary_free_all(dictionary *dictionary,void *data_manipulation)
 * [EN]
 * Frees memory of dictionary [dictionary_to_free].
 * [RU]
 * Освобождает память элемента словаря [dictionary_to_free].
*/
void *yon_dictionary_free(dictionary *dictionary_to_free);

/** void *yon_dictionary_free_all(dictionary *dictionary,void *data_manipulation)
 * [EN]
 * Frees whole [dictionary] and activates [data_manipulation] function if not NULL with [dictionary]->data argument for each dictionary.
 * [RU]
 * Освобождает память для всех элементов словаря [dictionary] и активирует функцию [data_manipulation], если она была передана, с аргументом [dictionary]->data на каждый элемент словаря.
*/
void *yon_dictionary_free_all(dictionary *dictionary,void (data_manipulation)(void*));

// char functions

#define yon_char_divide_search_self(str,find,delete_divider) {char *temp = str; str = yon_char_divide_search(str,find,delete_divider); free(temp);}

#define yon_char_is_empty(string) !(string&&strcmp(string,""))

#define yon_char_return_if_exist(string,opposite) string&&strcmp(string,"")?string:opposite

#define yon_char_remove_last_symbol(target,symbol) {if (target[strlen(target)-1]==symbol) target[strlen(target)-1]='\0';}

int yon_char_find_last(char *source, char find);

/**[EN]
 * 
 * creates new char string by combining two char strings.
 */
char *yon_char_append(char *source, char *append);

/**[EN]
 * 
 * creates new char string by copying another char.
 */
char *yon_char_new(char *chr);

/**yon_char_unite(char *source, ...)
 * [En]
 * 
 * [RU]
 * Объединяет строку [source] со всеми строками, написанными в [...]. Последний элемент должен быть NULL
*/
char *yon_char_unite(char *source, ...);

/**yon_cut(char *source, int size, int startpos)
 * [EN]
 * cuts source string by size length from startpos position.
 */
char *yon_cut(char *source, int size, int startpos);

/**yon_char_divide(char *source, int dividepos)
 * [EN]
 * divides source string in dividepos position,
 * returning left part of divided string and
 * inserting right part to source string.
 */
char *yon_char_divide(char *source, int dividepos);

/**yon_char_divide_search(char *source, char *dividepos, int delete_divider)
 * [EN]
 * char *yon_char_divide_search(char *source, char *dividepos, int delete_divider)
 * searches string [dividepos] in [source] string and divides it,
 * returning left part of divided string and
 * inserting right part to [source] string.
 * if [delete_divider] is 0, left part will contain [delete_divider] substring, else
 * if [delete_divider] is 1 it will stay in right part, else
 * if [delete_divider] is -1 it will be deleted from string.
 * 
 * [RU]
 * char *yon_char_divide_search(char *source, char *dividepos, int delete_divider)
 * Ищет строку [dividepos] в строке [source] и делит её в этом месте,
 * возвращая левую часть разделённой строки и устанавливает в [source] правую часть.
 * Если [delete_divider] равен 0, [dividepos] останется в левой строке, иначе
 * если [delete_divider] равен 1, [dividepos] останется в правой строке, иначе
 * если [delete_divider] равен -1, [dividepos] удаляется из строки.
 */
char *yon_char_divide_search(char *source, char *dividepos, int delete_divider);

/**yon_char_from_int(int int_to_convert)
 * [EN]
 * char *yon_char_from_int(int int_to_convert)
 * converts int to char*.
 * 
 * [RU]
 * char *yon_char_from_int(int int_to_convert)
 * Конвертирует int в char*
 */
char *yon_char_from_int(int int_to_convert);

/**yon_char_from_float(int int_to_convert)
 * [EN]
 * converts float to char*.
 * 
 * [RU]
 * Конвертирует float в char*
 */
char *yon_char_from_float(float int_to_convert);

/**yon_char_from_long(int int_to_convert)
 * [EN]
 * converts long to char*.
 * 
 * [RU]
 * Конвертирует long в char*
 */
char *yon_char_from_long(long int_to_convert);

/**yon_char_replace(char *source, char *find, char*replace)
 * [EN]
 * 
 * [RU]
 * Заменяет в строке [source] все вхождения строки [find] на [replace]
*/
char *yon_char_replace(char *source, char *find, char*replace);

/**yon_char_parse(char *parameters, int *size, char *divider)
 * [EN]
 * Parses string [parameters], divided by [divider],
 * then returns parsed string array and sets [size] to
 * size of returned array
*/
char **yon_char_parse(char *parameters, int *size, char *divider);

#define yon_char_parsed_add_or_create_if_exists(parsed,size,data) {if (!parsed) parsed = yon_char_parsed_new(size,data,NULL);\
                                                                    else parsed = yon_char_parsed_append(parsed,size,data);}

/**yon_char_parsed_rip(char **char_string, int *size, int item_to_delete)
 * [EN]
 * 
 * [RU]
 * Удаляет элемент [item_to_delete] из массива строк [char_string], размера [size]
 * Возвращает получившийся массив, в [size] загружается размер нового массива.
*/
char **yon_char_parsed_rip(char **char_string, int *size, int item_to_delete);

/**yon_char_parsed_check_exist(char **parameters, int size, char *param)
 * [EN]
 * Checks if [parameters] string array of length [size]
 * has [param] element;
 * [RU]
 * Проверяет есть ли в массиве строк [parameters], размера [size]
 * элемент [param]
*/
int yon_char_parsed_check_exist(char **parameters, int size, char *param);

/**yon_char_parsed_check_repeats(char **parameters, int size)
 * [EN]
 * Checks if [parameters] string array of length [size]
 * has repeated elements;
 * [RU]
 * Проверяет есть ли в массиве строк [parameters], размера [size]
 * повторения
*/
int yon_char_parsed_check_repeats(char **parameters, int size, int *first_overlap, int *second_overlap);

/**yon_char_find_count(char *source, char *find)
 * [EN]
 * 
 * [RU]
 * Считает количество символов [find] в строке [source]
*/
int yon_char_find_count(char *source, char *find);

/**yon_char_parsed_includes_char_parsed (config_str source, config_str to_check, int source_size, int check_size)
 * [EN]
 * 
 * [RU]
 * Проверяет, включает ли в себя [source] размера [source_size]
 * массив строк [to_check] размера [check_size]
*/
int yon_char_parsed_includes_char_parsed (config_str source, config_str to_check, int source_size, int check_size);

/**yon_char_parsed_new (config_str old, int *old_size, ...)
 * [EN]
 * 
 * [RU]
 * Создаёт новый массив строк. В [size] выгружается его размер
 * [...] - неограниченное количество строк.
*/
config_str yon_char_parsed_new (int *size, ...);

void yon_char_parsed_free(config_str source, int size);

/**config_str yon_char_parsed_copy(config_str to_copy, int size)
 * [EN]
 * 
 * [RU]
 * Возвращает копию массива строк [to_copy] размера [size]
*/
config_str yon_char_parsed_copy(config_str to_copy, int size);

/**config_str yon_char_parsed_append(config_str parsed, int *size, char *string)
 * [EN]
 * Adds [string] at the end of [parsed] string array of [size] length.
 * [RU]
 * Добавляет строку [string] в конец массива строк [parsed] с длинной [size].
*/
config_str yon_char_parsed_append(config_str parsed, int *size, char *string);

void yon_char_parsed_append_strings (config_str array, int size, char *prepend);

void yon_char_parsed_prepend_strings (config_str array, int size, char *prepend);

/**yon_char_parsed_merge(config_str array1, int size1, config_str array2, int size2, int *final_size)
 * [EN]
 * 
 * [RU]
 * Объединяет два массива строк в один.
 * [array1] - первый массив строк размера [size1]
 * [array2] - второй массив строк размера [size2]
 * [final_size] - указатель на целочисленную переменную в которую должен вернуться размер нового массива
*/
config_str yon_char_parsed_merge(config_str array1, int size1, config_str array2, int size2, int *final_size);

/**yon_char_parsed_merge_no_repeats(config_str array1, int size1, config_str array2, int size2, int *final_size)
 * [EN]
 * 
 * [RU]
 * Объединяет два массива строк в один с предотвращением дублей.
 * [array1] - первый массив строк размера [size1]
 * [array2] - второй массив строк размера [size2]
 * [final_size] - указатель на целочисленную переменную в которую должен вернуться размер нового массива
*/
config_str yon_char_parsed_merge_no_repeats(config_str array1, int size1, config_str array2, int size2, int *final_size);

int yon_char_parsed_divide_full(config_str parsed,int size,int divide_pos);

int yon_char_parsed_divide_search_full(config_str parsed,int size,char *divide_pos, int delete_divider);

dictionary *yon_char_parsed_convert_to_dictionary(config_str parsed, int size);

dictionary *yon_char_parsed_convert_copy_to_dictionary(config_str parsed, int size);

char *yon_char_parsed_to_string(config_str parsed, int size, char *divider_replace);

/**yon_ubl_check_root()
 * [EN]
 * 
 * [RU]
 * Возвращает 1 если приложение было запущено от root
*/
int yon_ubl_check_root();

/**yon_ubl_root_user_get()
 * [EN]
 * 
 * [RU]
 * Возвращает имя пользователя.
 * Если пользователь запустил приложение через root, выводится имя пользователя, запустившего приложение через root 
*/
char *yon_ubl_root_user_get();

/** yon_ubl_user_get_home_directory()
 * [EN]
 * 
 * [RU]
 * Возвращает домашний каталог пользователя.
 * Если пользователь открыл утилиту с правами суперпользователя, всё равно возвращает каталог пользователя, а не root
*/
char *yon_ubl_user_get_home_directory();

/** yon_ubl_get_all_users(int *user_size)
 * [EN]
 * 
 * [RU]
 * Возвращает массив всех пользователей в системе и записывает его размер в [user_size]
*/
config_str yon_ubl_get_all_users(int *user_size);

// parsing functions

/** yon_size_convert_automatic(int bytes, int *size)
 * [EN]
 * 
 * [RU]
 * Делит число [bytes] на 1024 пока оно не станет меньше 1024.
 * Возвращает получившееся число и устанавливает [size] равным количеству делений. 
*/
float yon_size_convert_automatic(int bytes, int *size);

apps *yon_apps_scan_and_parse_desktops(int *sizef);

void yon_apps_sort(apps *applist, int size);

apps *yon_apps_get_by_name(apps *applist, char *name, int size);

char *yon_file_path_proceed_spaces(char *path);

/**yon_file_open(char *file_path, int *size)
 * [EN]
 * 
 * [RU]
 * Открывает файл [file_path], возвращает содержимое в виде массива строк размера [size]
*/
config_str yon_file_open(char *file_path, int *size);

/**yon_file_create(char *path, char *name, int rules)
 * [EN]
 * 
 * [RU]
 * Создать файл с названием [name], находящимся по пути [path]
 * С правами доступа [rules] (от 0000 до 0777)
*/
int yon_file_create(char *path, char *name, int rules);

/**yon_file_create_full_path(char *path, char *name, int rules)
 * [EN]
 * 
 * [RU]
 * Создать файл по пути [path]
 * С правами доступа [rules] (от 0000 до 0777)
*/
int yon_file_create_full_path(char *path, int rules);

/** yon_dir_get_contents(char *dir_path, int *size)
 * [EN]
 * 
 * [RU]
 * Проверяет существует ли папка [dir_path] и
 * возвращает список всех вложенных файлов и папок,
 * передавая в [size] длину списка.
*/
config_str yon_dir_get_contents(char *dir_path, int *size);

//config functions

#define ubconfig_save_command "ubconfig "

#define ubconfig_load_command_old "ubconfig --source"

#define ubconfig_dull_command "ubconfig "
#define ubconfig_set_command(target) yon_char_unite("ubconfig ",!yon_char_is_empty(target)?"--target ":"",target," ",NULL)
#define ubconfig_load_command(target) yon_char_unite("ubconfig --source ",target," get ",NULL)
#define ubconfig_load_command_full(target, data) yon_char_unite("ubconfig --source ",target," get ",data,NULL)

/**
 * Типы конфигураций ubconfig-а
*/
typedef enum {
    YON_CONFIG_LOCAL=0,
    YON_CONFIG_GLOBAL,
    YON_CONFIG_BOTH,
    YON_CONFIG_DEFAULT,
    YON_CONFIG_CUSTOM
} YON_CONFIG_TYPE;

void yon_config_parameter_set_load_command(char *key, char *command);

void yon_config_parameter_set_save_command(char *key, char *command);

char *yon_config_parameter_get_load_command(char *key);

char *yon_config_parameter_get_save_command(char *key);

char *yon_config_get_type_path(YON_CONFIG_TYPE type);

/**yon_config_load(char *command, int *str_len)
 * [EN]
 * 
 * [RU]
 * Выполняет команду [command] и возвращает результат выполнения команды, разделяя на строки.
 * В [str_len] возвращается длина возвращаемого массива
*/
config_str yon_config_load(char *command, int *str_len);

config_str yon_config_load_file(FILE *file, int *str_len);

config_str yon_config_get_load_parameters_by_list(int *size, config_str parameters, int params_size);

config_str yon_config_get_save_parameters_by_list(int *size, config_str parameters, int params_size);

config_str yon_config_get_save_parameters_by_key(int *size, char *parameter,...);

config_str yon_config_get_save_parameters(int *size);

/**yon_config_parameter_prepare_command(char *command, char *path, char *section, char *parameter)
 * 
*/
char *yon_config_parameter_prepare_command(char *command, char *path, char *section, char *parameter);

/**int yon_config_save_registered(char *path)
 * [EN]
 * Saves config at [path] config. 
 * [path] can be:
 * system
 * global
 * [RU]
 * Сохраняет конфигурацию в [path] конфиг.
 * [path] может быть
 * system - локальный конфиг
 * global - глобальный конфиг
*/
[[ deprecated ( "Use yon_config_save_simple for simple saving instead (full-controlled saving is provided with libublsettingsui-gtk3 library)" ) ]]
int yon_config_save_registered(char *path);

/**char *yon_config_get_parameter(config parameters, int size, char *param)
 * [EN]
 * Gets parameter [param] from parameter list [parameters] of size [size];
 * or NULL if nothing were found
 * [RU] 
 * Возвращает параметр [param] из массива строк [parameters] размером [size]
 * или NULL если такой не был найден
*/
char *yon_config_get_parameter(config_str parameters, int size, char *param);

int yon_config_set_ignore(char *key);

int yon_config_remove_ignore(char *key);

int yon_config_get_status(char *key);

int yon_config_check_ignore(char *key);

int yon_config_parse_parameter(char *parameter,char **key, char **value);

int yon_char_remove_brackets(char *string);

int yon_config_load_config(YON_CONFIG_TYPE config_type, ...);

/**yon_config_load_register_no_cleaning(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...)
 * [EN]
 * 
 * [RU]
 * Считывает параметры [parameter] из раздела [section] ubconfig'а.
 * ... - пара из [section], [parameter], позволяющих загружать параметры из разных разделов конфига, оканчивающихся NULL.
 * Полученные данные парсятся и регистрируются в конфиг без удаления старых данных.
*/
[[ deprecated ( "Use yon_config_load_config instead" ) ]]
int yon_config_load_register_no_cleaning(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...);

/**yon_config_load_register(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...)
 * [EN]
 * 
 * [RU]
 * Считывает параметры [parameter] из раздела [section] ubconfig'а.
 * ... - пара из [section], [parameter], позволяющих загружать параметры из разных разделов конфига, оканчивающихся NULL.
 * Полученные данные парсятся и регистрируются в конфиг, удаляя старые значения.
*/
[[ deprecated ( "Use yon_config_load_config instead" ) ]]
int yon_config_load_register(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...);

/**yon_config_remove_by_key(char *key)
 * [EN]
 * 
 * [RU]
 * Удаляет параметр конфига по ключу [key]
*/
int yon_config_remove_by_key(char *key);

/**yon_config_remove_element(char *key, char *deleted)
 * [EN]
 * 
 * [RU]
 * Удаляет элемент [deleted] из массива параметров с ключом [key] 
*/
int yon_config_remove_element(char *key, char *delete_target, char *divider);

int yon_config_set_status(char *key, int status);

void yon_config_set_status_full(int status);

/**yon_config_get_key_by_key(char *data)
 * [EN]
 * 
 * [RU]
 * Возвращает значение параметра конфига с ключом [key].
 * Если параметр с таким значением не найден, возвращается NULL
*/
void *yon_config_get_by_key(char *key);

char *yon_config_get_section_for_key(char *key);

/**yon_config_get_all_by_key(char *data)
 * [EN]
 * 
 * [RU]
 * Возвращает значение всех параметров конфига с ключом включающем строку [key].
 * Если параметр с таким значением не найден, возвращается NULL
*/
void *yon_config_get_all_by_key(char *key, int *size);

/**yon_config_get_all_by_key(char *data)
 * [EN]
 * 
 * [RU]
 * Возвращает значение всех параметров конфига с ключом включающем строку [key] не включая игнорируемые параметры.
 * Если параметр с таким значением не найден, возвращается NULL
*/
void *yon_config_get_all_by_key_no_ignored(char *key, int *size);

/**yon_config_get_all_keys(int *size)
 * [EN]
 * 
 * [RU]
 * Возвращает массив с ключами всех параметров внутреннего конфига
*/
config_str yon_config_get_all_keys(int *size);

config_str yon_config_get_all_keys_no_ignored(int *size);

/**yon_config_set(char *key, void *data)
 * [EN]
 * 
 * [RU]
 * Производит поиск по конфигу и заменяет значение параметра с ключом [key] на новое значение [data];
*/
int yon_config_set(char *key, void *data);

/**yon_config_append(char *key, void *data)
 * [EN]
 * 
 * [RU]
 * Производит поиск по конфигу и дополняет значение параметра с ключом [key] значением [data];
*/
int yon_config_append(char *key, char *data, char *divider);

/**yon_config_clean()
 * [EN]
 * Erase all parameters from config;
 * [RU]
 * Удаляет все параметры из конфига;
*/
int yon_config_clean();

/**yon_config_register(char *key, void *data)
 * [EN]
 * 
 * [RU]
 * Регистрирует новый параметр конфига.
 * [key] - ключ параметра;
 * [data] - значение параметра;
*/
void yon_config_register(char *key, char* config_section, void *data);

char *yon_config_save_simple(YON_CONFIG_TYPE target, char *path);

/**int yon_config_force_save_registered(char *path, char *section)
 * [EN]
 * Force config to save at [path] config ignoring parameter save status. 
 * [path] can be:
 * system
 * global
 * [RU]
 * Принудительно сохраняет конфигурацию в [path] конфиг игнорируя статус параметра.
 * [path] может быть
 * system - локальный конфиг
 * global - глобальный конфиг
*/
[[ deprecated ( "Will be removed soon" ) ]]
int yon_config_force_save_registered(char *path);

/**yon_config_get_all(int *size)
 * [EN]
 * 
 * [RU]
 * Возвращает массив со всеми параметрами конфига, оканчивающаяся NULL
 * [size] - указатель, в который выгружается длина массива
*/
config_str yon_config_get_all(int *size);

config_str yon_config_get_all_no_ignored(int *size);

// terminal-using functions

/**yon_launch_app_with_arguments(char *name, char *args)
 * [EN]
 * Execute [command] in separate thread;
 * [RU]
 * Выполнить команду [command] в отдельном потоке;
*/
int yon_launch_app_with_arguments(char *name, char *args);

/**yon_launch(char *command)
 * [EN]
 * Execute command [command]
 * [RU]
 * Выполнить команду [command]
*/
void yon_launch(char *command);

// // Trash collector functions
// int yon_trash_collector_append(void *pointer, char group_key);

// int yon_trash_collector_free(char *group_key);

// void *yon_malloc(int size, char *group_key);

#endif