#include "ubl-settings-services-systemd.h"


void at_exit_cleanup();
sd_bus *global_bus=NULL;
void at_exit_cleanup(){
    if (global_bus) {
        sd_bus_unref(global_bus);
    }
}

dictionary *yon_systemd_get_list() {
    sd_bus *bus = NULL;
    sd_bus_message *reply = NULL;
    int r;

    r = sd_bus_open_system(&bus);
    if (r < 0) return NULL;

    dictionary *dict = NULL;

    r = sd_bus_call_method(bus,
        "org.freedesktop.systemd1",
        "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager",
        "ListUnits",
        NULL,
        &reply,
        "");
    if (r < 0) {if (bus) sd_bus_unref(bus);return NULL;}

    sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
    while (sd_bus_message_enter_container(reply, SD_BUS_TYPE_STRUCT, "ssssssouso") > 0) {
        const char *name, *description;
        const char *load_state, *active_state, *sub_state;
        const char *following, *unit_path;
        unsigned int job_id;
        const char *job_type, *job_path;

        sd_bus_message_read(reply, "ssssssouso",
            &name, &description,
            &load_state, &active_state,
            &sub_state, &following,
            &unit_path, &job_id,
            &job_type, &job_path);

        systemd_struct *u = calloc(1, sizeof(systemd_struct));
        u->name        = yon_char_new(name);
        u->description = yon_char_new(description);
        u->load        = !strcmp(load_state,"loaded");
        u->active      = !strcmp(active_state, "active");
        u->state       = yon_char_new(sub_state);
        u->enable      = 0;

        yon_dictionary_add_or_create_if_exists_with_data(dict, (char*)name, u);

        sd_bus_message_exit_container(reply);
    }
    sd_bus_message_unref(reply);
    reply = NULL;

    r = sd_bus_call_method(bus,
        "org.freedesktop.systemd1",
        "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager",
        "ListUnitFiles",
        NULL,
        &reply,
        "");
    if (r < 0) {if (bus)   sd_bus_unref(bus); return NULL;}

    sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
    while (sd_bus_message_enter_container(reply, SD_BUS_TYPE_STRUCT, "ss") > 0) {
        const char *name, *file_state;
        sd_bus_message_read(reply, "ss", &name, &file_state);

        dictionary *found = NULL;
        for (dictionary *it = dict; it; it = it->next) {
            if (strcmp(it->key, name) == 0) {
                found = it;
                break;
            }
        }
        if (!found) {
            char *temp_name = yon_char_new(name);
            if (!yon_dictionary_get(&dict,temp_name)){
                systemd_struct *u = calloc(1, sizeof(systemd_struct));
                free(yon_char_divide(temp_name,yon_char_find_last(temp_name,'/')));
                u->name        = temp_name;
                u->description = yon_char_new("");
                u->load        = 0;
                u->active      = 0;
                u->state = _("disabled");
                u->enable      = 0;

                yon_dictionary_add_or_create_if_exists_with_data(dict, (char*)temp_name, u);
            }
        }
        sd_bus_message_exit_container(reply);
    }
    sd_bus_message_unref(reply);
    reply = NULL;

    dictionary *it;
    for_dictionaries(it, dict) {
        systemd_struct *u = (systemd_struct*)it->data;
        r = sd_bus_call_method(bus,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "GetUnitFileState",
            NULL,
            &reply,
            "s", u->name);
        if (r >= 0) {
            const char *status;
            sd_bus_message_read(reply, "s", &status);
            u->enable = (strcmp(status, "enabled") == 0);
        }
        sd_bus_message_unref(reply);
        reply = NULL;
    }

    if (reply) sd_bus_message_unref(reply);
    if (bus)   sd_bus_unref(bus);
    return dict;
}