#include "libublsettings-gtk3.h"

GHashTable *__yon_timezone = NULL;

#define timezone_path "/usr/share/zoneinfo/zone.tab"
#define timezone_countries_path "/usr/share/zoneinfo/iso3166.tab"

#define yon_timezone_check if (__yon_timezone&&g_hash_table_size(__yon_timezone))

typedef struct {
    char *country_code;
    char *timezone;
    char *comments;
    char *city;
    char *country;
    char *zone;
    double lat;
    double lon;
} yon_timezone_struct;

void yon_timezone_add_custom(const char *timezone){
            yon_timezone_struct *timezone_info = malloc(sizeof(yon_timezone_struct));
            memset(timezone_info,0,sizeof(yon_timezone_struct));
        
        g_hash_table_insert(__yon_timezone,yon_char_new(timezone_info->timezone),timezone_info);

}

void yon_timezone_set_country(const char *timezone, const char *country){

}

void _yon_timezone_countries_setup(GHashTable *timezone_countries){
    g_hash_table_remove_all(timezone_countries);
    int size;
    config_str countries_file = yon_file_open(timezone_countries_path,&size);
    for (int i=0;i<size;i++){
        if (countries_file[i][0]=='#') continue;
        yon_char_remove_last_symbol(countries_file[i],'\n');

        int parsed_size;
        config_str parsed = yon_char_parse(countries_file[i],&parsed_size,"\t");
        if (size<2) continue;
        g_hash_table_insert(timezone_countries,yon_char_new(parsed[0]),yon_char_new(parsed[1]));
        yon_char_parsed_free(parsed,parsed_size);
    }
    yon_char_parsed_free(countries_file,size);
}

int yon_timezone_init(){
    yon_timezone_check{
        return 0;
    } else {
        GHashTable *timezone_countries = g_hash_table_new_full(g_str_hash, g_str_equal,free,free); 
        _yon_timezone_countries_setup(timezone_countries);
        __yon_timezone = g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
        int size;
        config_str timezone_file = yon_file_open(timezone_path,&size);
        for (int i=0;i<size;i++){
            if (timezone_file[i][0]=='#') continue;
            yon_char_remove_last_symbol(timezone_file[i],'\n');
            int parsed_size;
            config_str parsed = yon_char_parse(timezone_file[i],&parsed_size,"\t");
            if (parsed_size<3) continue;

            yon_timezone_struct *timezone_info = malloc(sizeof(yon_timezone_struct));
            memset(timezone_info,0,sizeof(yon_timezone_struct));

            if (yon_char_count(parsed[2],"/")>1){
                timezone_info->timezone = yon_char_new(parsed[2]);
                free(yon_char_divide_search(timezone_info->timezone,"/",-1));
            } else {
                timezone_info->timezone = yon_char_new(parsed[2]);
            }
            

            char *city = strstr(timezone_info->timezone,"/");
            if (city){
                city++;
            }
            char *zone = yon_char_new(timezone_info->timezone);
            char *temp = strstr(zone,"/");
            if (temp){
                temp[0]='\0';
            }
            timezone_info->country_code = yon_char_new(parsed[0]);
            timezone_info->city = yon_char_new(city);
            timezone_info->country = yon_char_new(g_hash_table_lookup(timezone_countries,parsed[0]));
            timezone_info->zone = zone;
            char *coords = yon_char_new(parsed[1]);
            char *pos = strstr(coords+1,"+");
            char *ngt = strstr(coords+1,"-");
            char *lat = coords;
            char *lon = !yon_char_is_empty(pos)?yon_char_new(pos):yon_char_new(ngt);

            if (parsed_size>3){
                timezone_info->comments = yon_char_new(parsed[3]);
            }
            g_hash_table_insert(__yon_timezone,yon_char_new(timezone_info->timezone),timezone_info);

            yon_char_parsed_free(parsed,parsed_size);
        }
        yon_char_parsed_free(timezone_file,size);
        g_hash_table_unref(timezone_countries);
    }    

    return 1;
}

void yon_timezone_unref(){
    yon_timezone_check{
        g_hash_table_unref(__yon_timezone);
        __yon_timezone = NULL;
    }
}

config_str yon_timezone_get_all(size_t *size){
    (*size) = 0;
    yon_timezone_check{
        config_str timezones = (config_str)g_hash_table_get_keys_as_array(__yon_timezone,(guint*)size);
        qsort(timezones,*size,sizeof(char*),(__compar_fn_t)yon_char_parsed_compare);
        return yon_char_parsed_copy(timezones,*size);
    }
    return NULL;
}


char *yon_timezone_get_country_code(const char *timezone){
    yon_timezone_check{
        yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezone);
        if (timezone_info){
            return yon_char_new(timezone_info->country_code);
        }
    }
    return NULL;
}

char *yon_timezone_get_comments(const char *timezone){
    yon_timezone_check{
        yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezone);
        if (timezone_info){
            return yon_char_new(timezone_info->comments);
        }
    }
    return NULL;
}

char *yon_timezone_get_city(const char *timezone){
    yon_timezone_check{
        yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezone);
        if (timezone_info){
            return yon_char_new(timezone_info->city);
        }
    }
    return NULL;
}

char *yon_timezone_get_country(const char *timezone){
    yon_timezone_check{
        yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezone);
        if (timezone_info){
            return yon_char_new(timezone_info->country);
        }
    }
    return NULL;
}

char *yon_timezone_get_zone(const char *timezone){
    yon_timezone_check{
        yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezone);
        if (timezone_info){
            return yon_char_new(timezone_info->zone);
        }
    }
    return NULL;
}

#define get_utc_command(tz) yon_char_unite("TZ='",tz,"' date +%z",NULL);

char *yon_timezone_get_utc(const char *timezone){
    char *command = get_utc_command(timezone);
    int size;
    config_str ret = yon_config_load(command,&size);
    if (size>0){
        yon_char_remove_last_symbol(ret[0],'\n');
        char *temp = yon_char_new(ret[0]);
        yon_char_parsed_free(ret,size);
        return temp;
    }
    return NULL;
}

config_str yon_timezone_get_zones_from_region(char *region, size_t *size){
    size_t timezones_size=0;
    (*size) = 0;
    yon_timezone_check{
        config_str zones_final = NULL;
        config_str timezones = (config_str)g_hash_table_get_keys_as_array(__yon_timezone,(guint*)&timezones_size);
        for (size_t i=0;i<timezones_size;i++){
            yon_timezone_struct *timezone_info = g_hash_table_lookup(__yon_timezone,timezones[i]);
            if (timezone_info&&!yon_char_is_empty(timezone_info->zone)&&!strcmp(timezone_info->zone,region)){
                yon_char_parsed_add_or_create_if_exists(zones_final,(int*)size,timezone_info->city);
            }
        }
        qsort(zones_final,*size,sizeof(char*),(__compar_fn_t)yon_char_parsed_compare);
        return zones_final;
    }
}