#include "libublsettings-gtk3.h"
#include <alpm.h>

gboolean __yon_option_use_full_path = 0;

void yon_packages_option_use_full_path_set(gboolean enable){
    __yon_option_use_full_path = enable;
}

struct packages {
    alpm_handle_t *packages_handle;
    int init_status;
} packages_struct = {};

int _yon_packages_get_db(){
    const char *root = "/";
    const char *dbpath = "/var/lib/pacman";
    const char *dbpath_local = "/var/lib/pacman/local";
    const char *config_path = "/etc/pacman.conf";
    packages_struct.packages_handle = alpm_initialize(root,dbpath,NULL);
    if (!packages_struct.packages_handle){
        packages_struct.packages_handle = alpm_initialize(root,dbpath_local,NULL);
    }
    if (!packages_struct.packages_handle){
        packages_struct.init_status=0;
        return 0;
    }
    int size = 0;
    config_str pacman_config = yon_file_open((char*)config_path,&size);
    char *pacman_config_full = yon_char_parsed_to_string(pacman_config,size,"");

    GRegex *regex = g_regex_new("^\\[.*\\]$",G_REGEX_MULTILINE,0,NULL);
    GMatchInfo *match = NULL;
    g_regex_match(regex,pacman_config_full,G_REGEX_MATCH_DEFAULT,&match);

    while (g_match_info_matches(match)){
        char *iter = g_match_info_fetch(match,0);
        if (iter[0]=='['){
            free(yon_char_divide(iter,0));
            yon_char_remove_last_symbol(iter,']');
        }
        if (strcmp(iter,"options")){
            alpm_register_syncdb(packages_struct.packages_handle,iter,ALPM_SIG_USE_DEFAULT);
        }
        g_match_info_next(match,NULL);
    }
    packages_struct.init_status=1;

    return 1;
}

alpm_list_t *_yon_packages_get_db_list(enum YON_PACKAGES_DB_TYPE type){
    alpm_list_t *db_list = NULL;
    switch(type){
        case YON_PACKAGES_LOCAL:
            alpm_db_t *database = alpm_get_localdb(packages_struct.packages_handle);
                if (!db_list) db_list = alpm_list_append(&db_list,database);
                else alpm_list_append(&db_list,database);
        break;

        case YON_PACKAGES_SYNC:
            alpm_list_t *sync_db = alpm_get_syncdbs(packages_struct.packages_handle);
            for (alpm_list_t *iter=sync_db;iter;iter=alpm_list_next(iter)){
                alpm_db_t *database = iter->data;
                if (!db_list) db_list = alpm_list_append(&db_list,database);
                else alpm_list_append(&db_list,database);
            }
        break;
        
        case YON_PACKAGES_ALL:{
                alpm_list_t *sync_db = alpm_get_syncdbs(packages_struct.packages_handle);
                for (alpm_list_t *iter=sync_db;iter;iter=alpm_list_next(iter)){
                    alpm_db_t *database = iter->data;
                    if (!db_list) db_list = alpm_list_append(&db_list,database);
                    else alpm_list_append(&db_list,database);
                }
            }
            {
                alpm_db_t *database = alpm_get_localdb(packages_struct.packages_handle);
                if (!db_list) db_list = alpm_list_append(&db_list,database);
                else alpm_list_append(&db_list,database);
            }
        break;

    }
    return db_list;
}

int yon_packages_init(){
    if (packages_struct.packages_handle) return 0;

    int status = _yon_packages_get_db();
    if (!status) return 0;

    return 1;
}

char *yon_packages_parse_path(char *package_name){
    if (!strstr(package_name,"/")) return NULL;
    int pos = yon_char_find_last(package_name,'/');
    char *path = yon_char_divide(package_name,pos);
    return path;
}

alpm_db_t *__yon_packages_find_db_by_name(char *db_name){
    alpm_list_t *sync_db = _yon_packages_get_db_list(YON_PACKAGES_ALL);

    alpm_list_t *iter;
    for (iter=sync_db;iter;iter=alpm_list_next(iter)){
        const char *cur_db_name = alpm_db_get_name(iter->data);
        if (!strcmp(cur_db_name, db_name)){
            return (alpm_db_t*)iter->data;
        }
    }
    return NULL;
}


int yon_packages_check_exist(const char *package_name){
    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package_name);
        char *db_name = yon_packages_parse_path(name_copy);
        package_name=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(YON_PACKAGES_ALL);
        }
    } else {
        databases = _yon_packages_get_db_list(YON_PACKAGES_ALL);
    }
    alpm_list_t *iter;
    for (iter=databases;iter;iter=alpm_list_next(iter)){
        alpm_db_t *database = iter->data;
        alpm_pkg_t *package = alpm_db_get_pkg(database,package_name);
        
        if (package) return 1;
    }
    return 0;
}

int yon_packages_check_installed(char *package_name){
        char *cur_package = yon_char_new(package_name);
    if (__yon_option_use_full_path){
        char *db_name = yon_packages_parse_path(cur_package);
        if (!yon_char_is_empty(db_name)) free(db_name);
    }
    alpm_db_t *database = alpm_get_localdb(packages_struct.packages_handle);
    alpm_pkg_t *package = alpm_db_get_pkg(database,cur_package);
    if (package) return 1;
    return 0;
}

int yon_packages_check_updates(char *package_name){
    alpm_pkg_t *sync_db_package = NULL;
    alpm_pkg_t *local_db_package = NULL;
    char *cur_package = yon_char_new(package_name);
    if (__yon_option_use_full_path){
        char *db_name = yon_packages_parse_path(cur_package);
        if (!yon_char_is_empty(db_name)) free(db_name);
    }

    alpm_list_t *sync_db = alpm_get_syncdbs(packages_struct.packages_handle);
    for (alpm_list_t *iter=sync_db;iter;iter=alpm_list_next(iter)){
        alpm_db_t *database = iter->data;
        alpm_pkg_t *package = alpm_db_get_pkg(database,cur_package);
        if (package) sync_db_package = package;
    }
    {
        alpm_db_t *database = alpm_get_localdb(packages_struct.packages_handle);
        alpm_pkg_t *package = alpm_db_get_pkg(database,cur_package);
        if (package) local_db_package = package;
    }

    if (sync_db_package && local_db_package){
        const char *sync_db_package_version = alpm_pkg_get_version(sync_db_package);
        const char *local_db_package_version = alpm_pkg_get_version(local_db_package);
        if (strcmp(sync_db_package_version,local_db_package_version)) return 1;
    }
    return 0;
}

config_str yon_packages_find(enum YON_PACKAGES_DB_TYPE type, const char *search_string, gsize *size){
    (*size)=0;
    if (yon_char_is_empty(search_string)) return NULL;

    config_str final = NULL;

    alpm_list_t *databases = _yon_packages_get_db_list(type);
    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_db_t *database = iter->data;
        alpm_list_t *packages = alpm_db_get_pkgcache(database);
        alpm_list_t *iter2 = NULL;
        for (iter2 = packages; iter2; iter2=iter2->next){
            const char *name = alpm_pkg_get_name(iter2->data);
            if (strstr(name,search_string)){
                if (yon_char_parsed_check_exist(final,(int)*size,(char*)name)==-1){
                    
                    char *full_name = NULL;
                    if (__yon_option_use_full_path){
                        const char *db_name = alpm_db_get_name(database);
                        full_name = yon_char_unite(db_name,"/",name,NULL);
                    } else {
                        full_name = yon_char_new(name);
                    }
                    yon_char_parsed_add_or_create_if_exists(final,(int*)size,full_name);
                }
            }
        }
    }
    return final;
}

char *yon_packages_get_version(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return NULL;

    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }
    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            return yon_char_new(alpm_pkg_get_version(pkg));
        }
    }
}

char *yon_packages_get_description(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return NULL;

    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }
    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            return yon_char_new(alpm_pkg_get_desc(pkg));
        }
    }
}

char *yon_packages_get_groups(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return NULL;
    
    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }

    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            alpm_list_t *groups = alpm_pkg_get_groups(pkg);
            alpm_list_t *iter;
            config_str groups_list = NULL;
            int parsed_size;
            int size = alpm_list_count(groups);

                for (int i=0;i<size;i++){
                    alpm_list_t *cur_data = alpm_list_nth(groups,i);
                    if (yon_char_parsed_check_exist(groups_list,parsed_size,cur_data->data)==-1){
                        yon_char_parsed_add_or_create_if_exists(groups_list,&parsed_size,yon_char_new(cur_data->data));
                    }
                }
            char *final = yon_char_parsed_to_string(groups_list,parsed_size,", ");
            return yon_char_new(final);
        }
    }
    return NULL;
}

long yon_packages_get_installed_size(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return 0;
    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }

    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            long size = alpm_pkg_get_isize(pkg);
            return size;
        }
    }
    return 0;
}

long yon_packages_get_size(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return 0;
    
    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }

    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            long size = alpm_pkg_get_size(pkg);
            return size;
        }
    }
    
    return 0;
}

char* yon_alpm_list_to_char(alpm_list_t *list){
    if (!list) return NULL;
    int size = 0;
    size_t list_size = alpm_list_count(list);
    config_str parsed = NULL;
    for (size_t i=0;i<list_size;i++){
        yon_char_parsed_add_or_create_if_exists(parsed,&size,list->data)
        list=list->next;
    }
    char *final = yon_char_parsed_to_string(parsed,size," ");
    yon_char_parsed_free(parsed,size);
    return final;
}

void yon_packages_info_struct_free(yon_packages_info *info){
    if (!yon_char_is_empty(info->repo_name)) free(info->repo_name);
    if (!yon_char_is_empty(info->package_name)) free(info->package_name);
    if (!yon_char_is_empty(info->version)) free(info->version);
    if (!yon_char_is_empty(info->description)) free(info->description);
    if (!yon_char_is_empty(info->architecture)) free(info->architecture);
    if (!yon_char_is_empty(info->url)) free(info->url);
    if (!yon_char_is_empty(info->licence)) free(info->licence);
    if (!yon_char_is_empty(info->groups)) free(info->groups);
    if (!yon_char_is_empty(info->provides)) free(info->provides);
    if (!yon_char_is_empty(info->depends)) free(info->depends);
    if (!yon_char_is_empty(info->optional_depends)) free(info->optional_depends);
    if (!yon_char_is_empty(info->conflicts)) free(info->conflicts);
    if (!yon_char_is_empty(info->replaces)) free(info->replaces);
    if (!yon_char_is_empty(info->download_size)) free(info->download_size);
    if (!yon_char_is_empty(info->install_size)) free(info->install_size);
    if (!yon_char_is_empty(info->packager)) free(info->packager);
    if (!yon_char_is_empty(info->build_date)) free(info->build_date);
    free(info);
}

yon_packages_info *yon_packages_get_info_struct(enum YON_PACKAGES_DB_TYPE type, const char *package){
    if (yon_char_is_empty(package)) return NULL;

    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        package=name_copy;
        if (!yon_char_is_empty(db_name)){
            alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
            databases = alpm_list_add(NULL,found_db);
        } else {
            databases = _yon_packages_get_db_list(type);
        }
    } else {
        databases = _yon_packages_get_db_list(type);
    }
    alpm_list_t *iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        const char *name = alpm_pkg_get_name(pkg);
        if (!strcmp(name,package)){
            yon_packages_info *package_info = malloc(sizeof(yon_packages_info));
            memset(package_info,0,sizeof(yon_packages_info));
            package_info->repo_name = yon_char_new(alpm_db_get_name(iter->data));
            package_info->package_name = yon_char_new(alpm_pkg_get_name(pkg));
            package_info->version = yon_char_new(alpm_pkg_get_version(pkg));
            package_info->description = yon_char_new(alpm_pkg_get_desc(pkg));
            package_info->architecture = yon_char_new(alpm_pkg_get_arch(pkg));
            package_info->url = yon_char_new(alpm_pkg_get_url(pkg));

            size_t size=0;
            alpm_list_t *licence_list = alpm_pkg_get_licenses(pkg);
            package_info->licence = yon_alpm_list_to_char(licence_list);
            // alpm_list_free(licence_list);

            alpm_list_t *groups_list = alpm_pkg_get_groups(pkg);
            package_info->groups = yon_alpm_list_to_char(groups_list);
            // alpm_list_free(groups_list);

            {
                alpm_list_t *provides_list = alpm_pkg_get_provides(pkg);
                size = alpm_list_count(provides_list);
                int parsed_size=0;
                config_str parsed = NULL;
                for (int i=0;i<size;i++){
                    yon_char_parsed_add_or_create_if_exists(parsed,&parsed_size,((alpm_depend_t*)alpm_list_nth(provides_list,i)->data)->name);
                }
                package_info->provides = yon_char_parsed_to_string(parsed,parsed_size, " ");
                // alpm_list_free(provides_list);
            }

            {
                alpm_list_t *depends_list = alpm_pkg_get_depends(pkg);
                size = alpm_list_count(depends_list);
                int parsed_size=0;
                config_str parsed = NULL;
                for (int i=0;i<size;i++){
                    
                    yon_char_parsed_add_or_create_if_exists(parsed,&parsed_size,((alpm_depend_t*)alpm_list_nth(depends_list,i)->data)->name);
                }
                package_info->depends = yon_char_parsed_to_string(parsed,parsed_size, "\n");
                // alpm_list_free(depends_list);
            }

            {
                alpm_list_t *optdepends_list = alpm_pkg_get_optdepends(pkg);
                size = alpm_list_count(optdepends_list);
                int parsed_size=0;
                config_str parsed = NULL;
                for (int i=0;i<size;i++){
                    yon_char_parsed_add_or_create_if_exists(parsed,&parsed_size,((alpm_depend_t*)alpm_list_nth(optdepends_list,i)->data)->name);
                }
                package_info->optional_depends = yon_char_parsed_to_string(parsed,parsed_size, " ");
                // alpm_list_free(optdepends_list);
            }

            {
                alpm_list_t *conflicts_list = alpm_pkg_get_conflicts(pkg);
                size = alpm_list_count(conflicts_list);
                int parsed_size=0;
                config_str parsed = NULL;
                for (int i=0;i<size;i++){
                    yon_char_parsed_add_or_create_if_exists(parsed,&parsed_size,((alpm_depend_t*)alpm_list_nth(conflicts_list,i)->data)->name);
                }
                package_info->conflicts = yon_char_parsed_to_string(parsed,parsed_size, " ");
                // alpm_list_free(conflicts_list);
            }

            {
                alpm_list_t *replaces_list = alpm_pkg_get_replaces(pkg);
                size = alpm_list_count(replaces_list);
                int parsed_size=0;
                config_str parsed = NULL;
                for (int i=0;i<size;i++){
                    yon_char_parsed_add_or_create_if_exists(parsed,&parsed_size,((alpm_depend_t*)alpm_list_nth(replaces_list,i)->data)->name);
                }
                package_info->replaces = yon_char_parsed_to_string(parsed,parsed_size, " ");
                // alpm_list_free(replaces_list);
            }
            
            int size_mod = 0;
            int fin_size = yon_size_convert_automatic(alpm_pkg_get_size(pkg),&size_mod);
            char *size_letter = yon_size_get_mod(size_mod);
            char *size_string = yon_char_from_int(fin_size);
            package_info->download_size = yon_char_unite(size_string,size_letter,NULL);
            free(size_string);
            
            size_mod = 0;
            fin_size = yon_size_convert_automatic(alpm_pkg_get_isize(pkg),&size_mod);
            size_letter = yon_size_get_mod(size_mod);
            size_string = yon_char_from_int(fin_size);
            package_info->install_size = yon_char_unite(size_string,size_letter,NULL);
            free(size_string);

            package_info->packager = yon_char_new(alpm_pkg_get_packager(pkg));
            GDateTime *datetime = g_date_time_new_from_unix_local(alpm_pkg_get_builddate(pkg));
            package_info->build_date = g_date_time_format(datetime,"%Ec");
            package_info->validate_by = alpm_pkg_get_validation(pkg);
            
            return package_info;
        }
    }
}

char *yon_packages_get_info_string(yon_packages_info *info){
    char *packager = yon_char_return_if_exist(info->packager,"");
    char *info_label = yon_char_unite(
    "<b>",_("Repository"),"</b>\t\t:",yon_char_return_if_exist(info->repo_name,""),"\n",
    "<b>",_("Name"),"</b>\t\t\t:",yon_char_return_if_exist(info->package_name,""),"\n",
    "<b>",_("Version"),"</b>\t\t:",yon_char_return_if_exist(info->version,""),"\n",
    "<b>",_("Description"),"</b>\t:",yon_char_return_if_exist(info->description,""),"\n",
    "<b>",_("Architecture"),"</b>\t:",yon_char_return_if_exist(info->architecture,""),"\n",
    "<b>",_("URL"),"</b>\t\t\t:",yon_char_return_if_exist(info->url,""),"\n",
    "<b>",_("Licenses"),"</b>\t\t:",yon_char_return_if_exist(info->licence,""),"\n",
    "<b>",_("Groups"),"</b>\t\t\t:",yon_char_return_if_exist(yon_char_replace(info->groups," ","    "),""),"\n",
    "<b>",_("Provides"),"</b>\t\t:",yon_char_return_if_exist(info->provides,""),"\n",
    "<b>",_("Depends On"),"</b>\t:",yon_char_return_if_exist(info->depends,""),"\n",
    "<b>",_("Optional Deps"),"</b>\t:",yon_char_return_if_exist(info->optional_depends,""),"\n",
    "<b>",_("Conflicts With"),"</b>\t:",yon_char_return_if_exist(info->conflicts,""),"\n",
    "<b>",_("Replaces"),"</b>\t\t:",yon_char_return_if_exist(info->replaces,""),"\n",
    "<b>",_("Download Size"),"</b>\t:",yon_char_return_if_exist(info->download_size,""),"\n",
    "<b>",_("Installed Size"),"</b>\t:",yon_char_return_if_exist(info->install_size,""),"\n",
    "<b>",_("Packager"),"</b>\t\t:",g_markup_escape_text(packager,strlen(packager)),"\n",
    "<b>",_("Build Date"),"</b>\t\t:",yon_char_return_if_exist(info->build_date,""),//"\n",
    // "<b>",_("Validated By"),"</b>\t:",yon_char_return_if_exist(info->architecture,""),
    NULL);
return info_label;
}

config_str yon_packages_get_depends(enum YON_PACKAGES_DB_TYPE type, const char *package, int *size){
    (*size)=0;
    if (yon_char_is_empty(package)) return NULL;
    config_str depends = NULL;

    alpm_list_t *databases = NULL;
    if (__yon_option_use_full_path){
        char *name_copy = yon_char_new(package);
        char *db_name = yon_packages_parse_path(name_copy);
        alpm_db_t *found_db = __yon_packages_find_db_by_name(db_name);
        databases = alpm_list_add(NULL,found_db);
    } else {
        databases = _yon_packages_get_db_list(type);
    }
    alpm_list_t *iter = NULL, *pkg_iter = NULL;
    for (iter = databases; iter; iter=iter->next){
        alpm_pkg_t *pkg = alpm_db_get_pkg(iter->data,package);
        if (!pkg) continue;
        alpm_list_t *list = alpm_pkg_compute_requiredby(pkg);
        for (pkg_iter = list; pkg_iter; pkg_iter=pkg_iter->next){
            yon_char_parsed_add_or_create_if_exists(depends,size,pkg_iter->data);
            
        }
        break;
    }

    return depends;
}

void yon_packages_update(){
    if (getuid()) return;
    if (packages_struct.packages_handle) alpm_release(packages_struct.packages_handle);
    packages_struct.packages_handle=NULL;
    _yon_packages_get_db();
}

#define install_package_command(packages) yon_char_unite("upac -S --no-confirm ",packages,NULL)
#define remove_package_command(packages) yon_char_unite("upac -R --no-confirm ",packages,NULL)

int yon_packages_install(char *package,VteTerminal *terminal){
    if (!packages_struct.init_status) return 0;
    char *command = install_package_command(package);
    if (!terminal){
    yon_terminal_window_launch(NULL,command,"","");
    } else {
        yon_terminal_integrated_start((GtkWidget*)terminal,command);
    }

    yon_packages_update();
    free(command);
}

int yon_packages_remove(char *package,VteTerminal *terminal){
    if (!packages_struct.init_status) return 0;
    char *command = remove_package_command(package);
    if (!terminal){
    yon_terminal_window_launch(NULL,command,"","");
    } else {
        yon_terminal_integrated_start((GtkWidget*)terminal,command);
    }

    yon_packages_update();
    free(command);
}

void yon_packages_finish(){
    if (!packages_struct.init_status) return;
    alpm_release(packages_struct.packages_handle);
}

GList *yon_packages_get_all(){
    if (!packages_struct.init_status) return NULL;

    GList *list = NULL;
    
    alpm_list_t *sync_db = alpm_get_syncdbs(packages_struct.packages_handle);
    for (alpm_list_t *iter=sync_db;iter;iter=alpm_list_next(iter)){
        alpm_db_t *database = iter->data;
        alpm_list_t *package_list = alpm_db_get_pkgcache(database);
        for (alpm_list_t *piter = package_list;piter;piter=piter->next){
            const char *cur_name = alpm_pkg_get_name(piter->data);
            char *full_name = NULL;
            if (__yon_option_use_full_path){
                const char *db_name = alpm_db_get_name(database);
                full_name = yon_char_unite(db_name,"/",cur_name,NULL);
            } else {
                full_name = yon_char_new(cur_name);
            }
            if (!list) list = g_list_append(list,full_name);
            else if (g_list_append(list,full_name)){};
        }
    }

    return list;
}

GList *yon_packages_search_all(char *pkgname_regex){
    if (!packages_struct.init_status) return NULL;

    GList *list = NULL;
    
    alpm_list_t *sync_db = alpm_get_syncdbs(packages_struct.packages_handle);
    for (alpm_list_t *iter=sync_db;iter;iter=alpm_list_next(iter)){
        alpm_db_t *database = iter->data;
        alpm_list_t *package_list = alpm_db_get_pkgcache(database);
        for (alpm_list_t *iter = package_list;iter;iter=iter->next){
            const char *cur_name = alpm_pkg_get_name(iter->data);
            if (g_regex_match_simple(pkgname_regex,cur_name,0,0)){
                char *full_name = NULL;
            if (__yon_option_use_full_path){
                const char *db_name = alpm_db_get_name(database);
                full_name = yon_char_unite(db_name,"/",cur_name,NULL);
            } else {
                full_name = yon_char_new(cur_name);
            }
                if (!list) list = g_list_append(list,full_name);
                else if (g_list_append(list,full_name)){};
            }
        }
    }

    return list;
}

int yon_packages_upac_init(){
    
}