#include "util.h"
#define yon_gtk_builder_get_widget(builder, widget_name) GTK_WIDGET(gtk_builder_get_object(builder, widget_name))
namespace Utils {
    
string format_str_size(int num, int index) {
    string value = "";
    value = to_string(num);
    if (num == 0) {
        return value;
    }
    if (index == 1) {
        value += "M";
    }
    else if (index == 2) {
        value += "G";
    }
    else if (index == 3) {
        value += "T";
    }
    return value;
}

array<vector<string>, 5> read_csv(const string& filename) {
    array<vector<string>, 5> array_vectors;
    vector<string> vec_option;
    vector<string> vec_opcision;
    ifstream file(filename);
    string line;
    char delimiter = ',';
    getline(file, line);
    while (getline(file, line)) {
        stringstream stream(line);
        string option;
        string opcision;
        getline(stream, option, delimiter);
        string line_local = stream.str();
        if (line_local.find("\"") != string::npos) {
            string str_delimiter = "\"";
            vector<int> point = find_all(line_local, str_delimiter);
            size_t len = point.size();
            if (len >= 2) {
                int index_start = point[len-2];
                int index_end = point[len-1];
                opcision = line_local.substr(index_start, index_end);
                index_end = opcision.find("\"");
                if (opcision.find("\"") != string::npos) {
                    opcision.replace(index_end, opcision.length(), "");
                }

            }
            else {
                opcision = "error";
            }

            
        }
        else{
            getline(stream, opcision, delimiter);
        }
        

        vec_option.push_back(option);
        vec_opcision.push_back(opcision);
    }

    array_vectors[0] = vec_option;
    array_vectors[1] = vec_opcision;
    return array_vectors;
}

string call(string cmd) {
    FILE *fp;
    int status;
    char path[PATH_MAX] = {0};
    fp = popen(cmd.c_str(), "r");
    if (fp == NULL) {
        exit(1);
    }  
    while (fgets(path, PATH_MAX, fp) != NULL) {
        break;  
    }
    status = pclose(fp);
    if (status == -1) {
        exit(1);
    }
    return path;
}

vector<int> find_all(string &str_ntp, string substr) {
    size_t index = 0;
    vector<int> sub_index;
    while ((index = str_ntp.find(substr, index)) != std::string::npos) {
        index += substr.length();
        sub_index.push_back(index);
    }
    return sub_index;
}

void str_remove(std::string& source, std::string to_remove) {
    string::size_type n = to_remove.length();
    for (string::size_type i = source.find(to_remove);
        i != string::npos;
        i = source.find(to_remove))
        source.erase(i, n);
}

void str_replace_all(std::string& str_base, string str_find, string sReplacement)
{
    size_t pos = 0, fpos;
    while ((fpos = str_base.find(str_find, pos)) != std::string::npos)
    {
        str_base.replace(fpos, str_find.size(), sReplacement);
        pos = fpos + sReplacement.size();
    }
}
std::vector<std::string> split(std::string text, char delim) {
    std::string line;
    std::vector<std::string> vec;
    std::stringstream ss(text);
    while(std::getline(ss, line, delim)) {
        vec.push_back(line);
    }
    return vec;
}

int synopsis_show(string str_link) {
    // gettext("https://wiki.ublinux.com/ru/Программное_обеспечение/Программы_и_утилиты/Все/")
    string cmd = "xdg-open " + str_link;
    if (geteuid() == 0) {
        string response_user = getlogin();
        cmd = "su -l " + response_user + " -c \" DISPLAY=$DISPLAY " + cmd + " \"";
    }
    return system(cmd.c_str());
}

string file_read(string filename) {
    string line;
    string buffer; 
    std::ifstream in(filename); // окрываем файл для чтения
    if (in.is_open())
    {
        while (getline(in, line))
        {
            buffer += line;
        }
    }
    return buffer;
}

unsigned short read_uid_min_max(string filename, string search) {
    std::string line;
    int uid = 0;
    string remove_tab = "\t";
    string remove_space = " ";
    std::ifstream in(filename); // окрываем файл для чтения
    if (in.is_open()){
        while (getline(in, line)){
            try{
                if (line.find(search) != string::npos && (line.find("SYS_"+search) == string::npos)) {
                    Utils::str_remove(line, search);
                    Utils::str_remove(line, remove_space);
                    Utils::str_remove(line, remove_tab);
                    uid = atoi(line.c_str());
                }
            }
            catch (int x) {
                if (search == "UID_MIN"){
                    uid = 1000;
                }
                else{
                    uid = 65534;
                }

            }

        }
    }
    else{
        if (search == "UID_MIN") {
            uid = 1000;
        }
        else{
            uid = 65534;
        }
    }
    in.close(); 
    return uid;

}

vector<string> pars_users() {
    unsigned short uid_min = Utils::read_uid_min_max(file_source_login_min_max, "UID_MIN");
    unsigned short uid_max = Utils::read_uid_min_max(file_source_login_min_max, "UID_MAX");
    vector<string> vec_user;
    while (true) {
        errno = 0;
        passwd* entry = getpwent();
        if (!entry) {
            if (errno) {
                break;
            }
            break;
        }
        if ((entry->pw_uid >= uid_min && entry->pw_uid < uid_max) || entry->pw_uid == 0) {
            vec_user.push_back(entry->pw_name);
        }
    }
    endpwent();
    return vec_user;
}

vector<string> list_groups() {
    string str_uid_min = "UID_MIN";
    string str_uid_max = "UID_MAX";
    unsigned short uid_min = Utils::read_uid_min_max(file_source_login_min_max, "UID_MIN");
    unsigned short uid_max = Utils::read_uid_min_max(file_source_login_min_max, "UID_MAX");
    vector<string> str_users;
    while (1) {
        errno = 0;
        struct passwd* entry = getpwent();
        if (!entry) {
            if (errno) {
                return str_users;
            }
            break;
        }
        if ((entry->pw_uid >= uid_min && entry->pw_uid < uid_max) || entry->pw_uid == 0) {
            str_users.push_back(entry->pw_name);
        }
    }
    endpwent();
    return str_users;
}

vector<string> pars_group() {
    vector<string> vec_group;
    while (true) {
        errno = 0; // so we can distinguish errors from no more entries
        passwd* entry = getpwent();
        if (!entry) {
            if (errno) {
                std::cerr << "Error reading password database\n";
                break;
            }
            break;
        }
        vec_group.push_back(entry->pw_name);
    }
    endpwent();
    return vec_group;
}
}