/*
 * Tools : memory management, file loading and saving
 */

#include "defines.h"
#include "variables.h"
#include "tools.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <ctype.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include "configfile.h"


int fexist(const char *filename)
{
        FILE *file;

        if ( (file = fopen(filename, "r") ) == NULL) return FALSE;
        fclose(file);

        return TRUE;
}


void mbox_add(MailBox **list, const char *value)
{
        MailBox *lst = *list;
        int ok = TRUE;
        char box[100];
        char user[25];
        char pass[25];
        char btype[10];
        char folder[100];
        int count;

        if (! value) return ;
        memset(box, 0, 100);
        memset(btype, 0, 10);
        memset(user, 0, 25);
        memset(pass, 0, 25);
        memset(folder, 0, 100);
        count = sscanf(value, "%s %s %s %s %s", btype, box, user, pass, folder);

        if (((strcmp(btype, "MBOX") == 0) ||
             (strcmp(btype, "MAILDIR") == 0) ||
             (strcmp(btype, "MH") == 0)) &&
            count < 2)
        {
                fprintf(stderr, "Invalid Mail box parameters !\n");
                return ;
        }

        if ( ((strcmp(btype, "MBOX") == 0) ||
              (strcmp(btype, "MAILDIR") == 0) ||
              (strcmp(btype, "MH") == 0) ) &&
             (! fexist(box)))
        {
                fprintf(stderr, "Mail box '%s' does not exist !\n", box);
                return ;
        }
        if (! lst)
        {
                lst = xmalloc(sizeof(MailBox));
                *list = lst;
        }
        else
        {
                if (strcmp(value, lst->entry) == 0) ok = FALSE;
                while ( (lst->next) && ok)
                {
                        lst = lst->next;
                        if (strcmp(value, lst->entry) == 0) ok = FALSE;
                }
                if (! ok) return ;
                lst->next = xmalloc(sizeof(MailBox));
                lst = lst->next;
        }
        lst->entry = xstrdup(box);
        lst->type = xstrdup(btype);
        lst->username = user ? xstrdup(user) : NULL;
        lst->password = pass ? xstrdup(pass) : NULL;
        lst->folder = folder ? xstrdup(folder) : NULL;
        lst->next = NULL;
}


void free_mbox(MailBox **list)
{
        MailBox *lst = *list, *next;
        while (lst)
        {
                next = lst->next;
                FREE(lst->entry);
                FREE(lst->type);
                FREE(lst->username);
                FREE(lst->password);
                FREE(lst->folder);
                free(lst);
                lst = next;
        }
        *list = NULL;
}


int nb_mbox(MailBox *list)
{
        MailBox *box = list;
        int n = 0;
        while (box)
        {
                n++;
                box = box->next;
        }
        return n;
}


void *xmalloc(size_t size)
{
        void *ret = malloc(size);
        if (ret == NULL)
        {
                perror("malloc() ");
                exit( -1);
        }
        else
                return ret;
}


char *xstrdup(const char *string)
{
        char *ret = strdup(string);
        if (ret == NULL)
        {
                perror("strdup() ");
                exit( -1);
        }
        else
                return ret;
}


int getbool(char *value)
{
        int i;
        for (i = 0 ; value[i] ; i++) value[i] = tolower(value[i]);
        if (strcmp(value, "0") == 0) return FALSE;
        if (strcmp(value, "1") == 0) return TRUE;
        if (strcmp(value, "true") == 0) return TRUE;
        if (strcmp(value, "false") == 0) return FALSE;
        if (strcmp(value, "yes") == 0) return TRUE;
        if (strcmp(value, "no") == 0) return FALSE;
        if (strcmp(value, "on") == 0) return TRUE;
        if (strcmp(value, "off") == 0) return FALSE;
        fprintf(stderr, "Error in converting \"%s\" to boolean value.\n", value);
        return FALSE;
}


void load_cfgfile()
{
        FILE *file;
        int i = 0;
        char line[MAXSTRLEN + 1];
        char *value;

        if ( (file = fopen(config_file, "r")) == NULL)
        {
                if (strstr(config_file, "/"DEFAULT_CFGFILE) == NULL)
                        fprintf(stderr, "Unable to open configuration file \"%s\".\n",
                                config_file);
                return ;
        }
        while (! feof(file))
        {
                memset(line, 0, MAXSTRLEN + 1);
                fgets(line, MAXSTRLEN, file);
                i++;
                if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0;
                if ( (line[0] == '#') || (line[0] == 0) ) continue;
                value = strchr(line, '=');
                if (! value) continue;
                value++;
                while ( (value[0] == ' ') && (value[0] != 0) ) value++;
                if (value[0] == 0) continue;

                if (strncmp(line, "Backlight", 9) == 0)
                        backlight = getbool(value);
                else if (strncmp(line, "Color", 5) == 0)
                        light_color = xstrdup(value);
                else if (strncmp(line, "Interval", 8) == 0)
                        update_interval = atoi(value);
                else if (strncmp(line, "Mailbox", 7) == 0)
                        mbox_add(&mboxes, value);
                else if (strncmp(line, "Command", 7) == 0)
                        command = xstrdup(value);
                else if (strncmp(line, "Notify", 6) == 0)
                        notif_cmd = xstrdup(value);
                else if (strncmp(line, "Blink", 5) == 0)
                        switch_authorized = getbool(value);
                else if (strncmp(line, "DefaultBox", 10) == 0)
                        boxnum = atoi(value);
                else if (strncmp(line, "CheckDelay", 9) == 0)
                        check_delay = atoi(value);
                else if (strncmp(line, "RunOnce", 7) == 0)
                        run_once = getbool(value);
                else if (strncmp(line, "CheckSize", 9) == 0)
                        test_size = getbool(value);
                else
                        fprintf(stderr, "Error in %s at line %d :\n[%s].\n",
                                config_file, i, line);
        }
}


char *robust_home()
{
        if (getenv("HOME"))
                return getenv("HOME");
        else if (getenv("USER") && getpwnam(getenv("USER")))
                return getpwnam(getenv("USER"))->pw_dir;
        else if (getenv("LOGNAME") && getpwnam(getenv("LOGNAME")))
                return getpwnam(getenv("LOGNAME"))->pw_dir;
        else if ((getuid() != -1) && (getpwuid(getuid())))
                return getpwuid(getuid())->pw_dir;
        else
                return "/";
}


void save_cfgfile()
{
        FILE *file;
        MailBox *box = mboxes;

        if ( (file = fopen(config_file, "w")) == NULL)
        {
                if (strstr(config_file, "/"DEFAULT_CFGFILE) == NULL)
                        fprintf(stderr, "Unable to open configuration file \"%s\".\n",
                                config_file);
                return ;
        }

        fprintf(file, configfile,
                backlight ? "On" : "Off",
                light_color ? light_color : "",  /*"#6ec63b",*/
                test_size ? "True" : "False",
                update_interval,
                command ? command : "",
                notif_cmd ? notif_cmd : "",
                switch_authorized ? "Yes" : "No",
                boxnum,
                check_delay < 15 ? 15 : check_delay,
                run_once ? "True" : "False");
        while (box)
        {
                fprintf(file, mboxline,
                        box->type,
                        box->entry,
                        box->username ? " " : "",
                        box->username ? box->username : "",
                        box->password ? " " : "",
                        box->password ? box->password : "",
                        box->folder ? " " : "",
                        box->folder ? box->folder : "");
                box = box->next;
        }
        fclose(file);
}
