#include "libublsettings.h"



dictionary *yon_dictionary_new()
{
    dictionary *dict = malloc(sizeof(dictionary));
    dict->data = NULL;
    dict->key = NULL;
    dict->next = NULL;
    dict->prev = NULL;
    dict->first = dict;
    dict->data_type = DICTIONARY_OTHER_TYPE;
    return dict;
}

dictionary *yon_dictinoary_copy(dictionary *dict){
    dictionary *dct = yon_dictionary_new_with_data(dict->key,dict->data);
    dct->data_type= dict->data_type;
    return dct;
}

dictionary *yon_dictionary_copy_deep(dictionary *dict){
    dictionary *dct = NULL;
    dictionary *newone=NULL;
    for_dictionaries(dct,dict){
        yon_dictionary_add_or_create_if_exists_with_data(newone,dct->key,dct->data);
        newone->data_type=dct->data_type;
    }
    return newone->first;
}

int yon_dictionary_set_data(dictionary *dict, void *data){
    if (!dict) return 0;
    dict->data=data;
    return 1;
}

int yon_dictionary_set_key(dictionary *dict, char *key){
    if (!dict||yon_char_is_empty(key)) return 0;
    dict->key=key;
    return 1;
}

int yon_dictionary_set(dictionary *dict, char *key, void *data){
    if (!dict||yon_char_is_empty(key)) return 0;
    dict->key=key;
    dict->data=data;
    return 1;
}

int yon_dictionary_empty(dictionary *dict){
    dict->data=NULL;
    dict->data_type=DICTIONARY_OTHER_TYPE;
    return 1;
}

void yon_dictionary_switch_to_last(dictionary **dict)
{
    dictionary *dct=NULL, *dact=*dict;
    for_dictionaries(dct,dact);
}

dictionary *yon_dictionary_append(dictionary *targetdict)
{
    targetdict = yon_dictionary_get_last(targetdict);
    targetdict->next = yon_dictionary_new();
    targetdict->next->prev = targetdict;
    targetdict->next->first = targetdict->first;
    targetdict->next->data_type = DICTIONARY_OTHER_TYPE;
    return targetdict->next;
}

dictionary *yon_dictionary_get_last(dictionary *dict)
{
    if (dict->next){
        dictionary *dct = NULL;
        for_dictionaries(dct,dict)
            if (!dct->next)
                return dct;
    } else return dict;
}

dictionary *yon_dictionary_swap(dictionary *dict, int aim)
{
    if (aim < 0)
    {
        if (dict->prev)
        {
            if (dict->prev->prev)
            {
                dictionary *next = dict->next, *prev = dict->prev, *preprev = prev->prev;
                if (next)
                {
                    preprev->next = dict;
                    dict->prev = preprev;
                    dict->next = prev;
                    prev->prev = dict;
                    prev->next = next;
                    next->prev = prev;
                }
                else
                {
                    preprev->next = dict;
                    dict->prev = preprev;
                    dict->next = prev;
                    prev->prev = dict;
                    prev->next = NULL;
                }
                return prev;
            }
            else
            {
                dictionary *next = dict->next, *prev = dict->prev;
                if (next)
                {
                    yon_dictionary_make_first(dict);
                    dict->prev = NULL;
                    dict->next = prev;
                    prev->prev = dict;
                    prev->next = next;
                    next->prev = prev;
                }
                else
                {
                    dict->prev = NULL;
                    dict->next = prev;
                    prev->prev = dict;
                    prev->next = NULL;
                }
                return prev;
            }
        }
    }
    else if (aim > 0)
    {
        if (dict->next)
        {
            if (dict->next->next)
            {
                dictionary *next = dict->next, *prev = dict->prev, *afnext = next->next;
                if (prev)
                {
                    prev->next = next;
                    next->prev = prev;
                    next->next = dict;
                    dict->prev = next;
                    dict->next = afnext;
                    afnext->prev = dict;
                }
                else
                {
                    yon_dictionary_make_first(next);
                    next->prev = NULL;
                    next->next = dict;
                    dict->prev = next;
                    dict->next = afnext;
                    afnext->prev = dict;
                }
                return next;
            }
            else
            {
                dictionary *next = dict->next, *prev = dict->prev;
                if (prev)
                {
                    prev->next = next;
                    next->prev = prev;
                    next->next = dict;
                    dict->prev = next;
                    dict->next = NULL;
                }
                else
                {
                    next->prev = NULL;
                    next->next = dict;
                    dict->prev = next;
                    dict->next = NULL;
                }
            }
        }
    }
}

void yon_dictionary_make_first(dictionary *dict)
{
    for (dictionary *dct = dict->first; dct != NULL; dct = dct->next)
    {
        dct->first = dict;
    }
}

void yon_dictionary_make_nth(dictionary *dict, int nth)
{
    dictionary *dct = dict->first;
    for (int i = 0; i < nth; i++)
    {
        if (dct == NULL)
            return;
        else
            dct = dct->next;
    }
    yon_dictionary_rip(dict);
    dictionary *prev = dct->prev;
    prev->next = dict;
    dict->prev = prev;
    dict->next = dct;
    dct->prev = dict;
}

dictionary *yon_dictionary_new_with_data(char *key, void *data)
{
    dictionary *dct = yon_dictionary_new();
    dct->key = yon_char_new(key);
    dct->data = data;
    dct->data_type = DICTIONARY_OTHER_TYPE;
    return dct;
}

void *yon_dictionary_free(dictionary *dictionary_to_free){
    if (dictionary_to_free){
        free(dictionary_to_free->data);
        free(dictionary_to_free->key);
        free(dictionary_to_free);
        return NULL;
    }
}

void yon_dictionary_free_all(dictionary *dictionary_to_free,void (*data_manipulation)(void*)){
    if (dictionary_to_free){
        dictionary *dict=NULL;
        for_dictionaries(dict,dictionary_to_free){
            if(data_manipulation)
                data_manipulation(dict->data);
            if(dict->prev)
                free(dict->prev);
        }
        free(dict);
    }
}

dictionary *yon_dictionary_append_with_data(dictionary *dict, char *key, void *data)
{
    dictionary *dct = yon_dictionary_append(dict);
    dct->key = yon_char_new(key);
    dct->data = data;
    dct->data_type = DICTIONARY_OTHER_TYPE;
    return dct;
}

int yon_dictionary_connect(dictionary *old, dictionary *toconnect)
{
    if (!old||!toconnect) return 0;
    dictionary *dict = yon_dictionary_get_last(old);
    dict->next = toconnect;
    toconnect->prev = dict;
    toconnect->first = dict->first;
    return 1;
}

int yon_dictionary_merge(dictionary *dict1,dictionary *dict2){
    if (!dict1||!dict2) return 0;
    dictionary *dct = NULL;
    for_dictionaries(dct,dict2){
        if (!yon_dictionary_get(&dict1,dct->key))
            yon_dictionary_connect(dict1,dct);
    }
    return 1;
}

dictionary *yon_dictionary_get(dictionary **dict, char *key)
{
    dictionary *dct = *dict;
    if (dct){
        for (dictionary *pointer = dct->first; pointer != NULL; pointer = pointer->next){
            if (pointer->key&&strcmp(pointer->key, key) == 0){
                *dict = pointer;
                return pointer;
            }
        }
    }
    return NULL;
}

dictionary *yon_dictionary_rip(dictionary *dict)
{
    if (!dict->next&&!dict->prev) {
        free(dict);
        return NULL;
    }
    else if (!dict->next)
    {
        dictionary *prev = dict->prev;
            free(dict);
        if (prev)
        {
            prev->next = NULL;
            return prev;
        }
    }
    else if (!dict->prev)
    {
        dictionary *next = dict->next;
        if (next)
        {
            yon_dictionary_make_first(next);
            next->prev = NULL;
            free(dict);
            return next;
        }
    }
    else
    {
        dictionary *next = dict->next, *prev = dict->prev;
        next->prev = prev;
        prev->next = next;
        free(dict);
        return next;
    }
}

dictionary *yon_dictionary_get_nth(dictionary *dict, int place)
{
    if (dict){
        dict = dict->first;
        int i = 0;
        for (i = 0; i < place; i++)
            if (dict->next)
                dict = dict->next;
            else
                break;
        if (i == place)
            return dict;
        else
            return NULL;
    } else return NULL;
}


dictionary *yon_dictionary_sort(dictionary *dict){
    dictionary *first = dict->first;
    dictionary *prev = first;
    dictionary *current = first->next;
    while (current){
        if (current!=prev&&strcmp(current->key,prev->key)<0){
            if (current->next)
                current->next->prev=prev;
            prev->next=current->next;
            current->next=prev;
            current->prev=prev->prev;
            if (prev->prev)
                prev->prev->next=current;
            prev->prev=current;
            if (prev==prev->first){
                yon_dictionary_make_first(current);
            }
            dictionary *temp = prev;
            prev = current;
            current=temp;
        }
        prev=prev->next;
        current = current->next;
    }
    return first;
}

int _yon_dictionary_check_loops(dictionary *_REG_DICT,dictionary *link){
    if (_REG_DICT){
        dictionary *dict;
        for_dictionaries(dict,_REG_DICT){
            if (dict->data==link){
                return 1;
            }
        }
    }
    return 0;
}

dictionary *yon_dictionary_check_loops(dictionary *target){
    dictionary *found = NULL;
    dictionary *dict;
    for_dictionaries(dict,target){
        if (_yon_dictionary_check_loops(found,dict)){
            return dict;
        } else {
            yon_dictionary_add_or_create_if_exists_with_data(found,NULL,dict);
        }
    }
    yon_dictionary_free_all(found,NULL);

    found = NULL;
    dict=yon_dictionary_get_last(target);
    for(;dict;dict=dict->prev){
        if (_yon_dictionary_check_loops(found,dict)){
            return dict;
        } else {
            yon_dictionary_add_or_create_if_exists_with_data(found,NULL,dict);
        }
    }
    yon_dictionary_free_all(found,NULL);
    return NULL;
}