#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <misclib.h>

#include "connap.h"
#include "command.h"
#include "io.h"
#include "search.h"
#include "config.h"
#include "shared.h"
/* #include "hotlist.h" */
#include "sound.h"
#include "util.h"


static char *rc_file;


static void get_config_string(char **s, int accept_empty)
{
   char *p;

   if (! (p = strtok(NULL, "\0")))
               goto empty;
   while (isspace(*p))
               p++;
   if (! *p)
               goto empty;
   free(*s);
       *s = new_string(p);
   return;

empty:
   if (accept_empty) {
               free(*s);
               *s = new_string("");
   } else {
               fprintf(stderr, "Missing configuration value in connap.cfg\n");
               exit(1);
   }
}


static void get_config_int(int *val)
{
   char *p;

   if (! (p = strtok(NULL, "\0")))
               goto error;
   while (isspace(*p))
               p++;
   if (! *p)
               goto error;
   *val = atoi(p);
   return;

error:
   fprintf(stderr, "Missing configuration value in connap.cfg\n");
   exit(1);
}


static void get_config_servers(void)
{
   char *p, *tmp, *name, *port_string, *meta_string;
   SERVER *new_server, *prev_server = NULL;

   while (servers) {
               free(servers->name);
               p = (char*)servers;
               servers = servers->next;
               free(p);
   }

   while ((p = strtok(NULL, " \t"))) {
               while (isspace(*p))
               p++;
               if (! *p) {
               return;
               }

               tmp = new_string(p);

               if (! split_server(tmp, &name, &port_string, &meta_string)) {
               fprintf(stderr, "Invalid server format in connap.cfg\n");
               exit(1);
               }

               new_server = (SERVER*)malloc(sizeof(SERVER));
               new_server->name = (char*)malloc(strlen(name) + 1);
               strcpy(new_server->name, name);
               new_server->port = atoi(port_string);
               new_server->meta = atoi(meta_string);
               new_server->next = NULL;

               if (! servers)
               servers = new_server;
               if (prev_server)
               prev_server->next = new_server;

               prev_server = new_server;
               free(tmp);
   }

   if (! servers)
               return;
   if (cur_server.name)
               free(cur_server.name);
       cur_server.name = new_string(servers->name);
   cur_server.port = servers->port;
   cur_server.meta = servers->meta;
}


static void get_config_auto_commands(void)
{
   char *p, *tmp;
   AUTOCOMMAND *new_command, *prev_command = NULL;

   while ((p = strtok(NULL, ";"))) {
               while (isspace(*p))
               p++;
               if (! *p)
               return;
               tmp = new_string(p);

               new_command = (AUTOCOMMAND*)malloc(sizeof(AUTOCOMMAND));
               new_command->data = new_string(tmp);
               new_command->next = NULL;

               if (! auto_commands)
               auto_commands = new_command;

               if (prev_command)
               prev_command->next = new_command;

               prev_command = new_command;
               free(tmp);
   }
}


static void get_config_shared_dirs(void)
{
   char *p;
   SHAREDDIR *new_dir, *prev_dir = NULL;

   while ((p = strtok(NULL, ":"))) {
               while (isspace(*p))
               p++;
               if (! *p)
               return;

               new_dir = (SHAREDDIR *)malloc(sizeof(SHAREDDIR));
               new_dir->dir_name = new_string(p);
               new_dir->next = NULL;

               if (! shared_dirs)
               shared_dirs = new_dir;
               if (prev_dir)
               prev_dir->next = new_dir;

               prev_dir = new_dir;
   }
}


static void read_config(FILE *f)
{
   char s[4097], *p;

   while (fgets(s, 4096, f)) {
               s[strlen(s) - 1] = 0;
               if (! strlen(s))
               continue;
               if (! (p = strtok(s, " \t")))
               continue;

               if (! strcmp(p, "username")) {
                       get_config_string(&user_info.user_name, 0);

               } else if (! strcmp(p, "password")) {
               get_config_string(&user_info.password, 0);

               } else if (! strcmp(p, "email")) {
               get_config_string(&user_info.email, 0);

               } else if (! strcmp(p, "dataport")) {
               get_config_int(&user_info.data_port);

               } else if (! strcmp(p, "linktype")) {
               get_config_int(&user_info.link_type);

               } else if (! strcmp(p, "registered")) {
               get_config_int(&user_info.registered);

               } else if (! strcmp(p, "dldir")) {
               get_config_string(&init_dl_dir, 0);

               } else if (! strcmp(p, "uldirs")) {
               get_config_shared_dirs();

               } else if (! strcmp(p, "servers")) {
               get_config_servers();

               } else if (! strcmp(p, "minlink")) {
               get_config_string(&cur_search.min_link, 0);
                       def_search.min_link = new_string(cur_search.min_link);

               } else if (! strcmp(p, "minfreq")) {
               get_config_string(&cur_search.min_freq, 0);
                       def_search.min_freq = new_string(cur_search.min_freq);

               } else if (! strcmp(p, "minbitrate")) {
               get_config_string(&cur_search.min_bitrate, 0);
                       def_search.min_bitrate = new_string(cur_search.min_bitrate);

               } else if (! strcmp(p, "maxfiles")) {
               get_config_string(&cur_search.max_files, 0);
                       def_search.max_files = new_string(cur_search.max_files);

               } else if (! strcmp(p, "showpath")) {
               get_config_int(&show_path);

       } else if (! strcmp(p, "timeout")) {
               get_config_int(&time_out);

       } else if (! strcmp(p, "autocommands")) {
               get_config_auto_commands();

       } else if (! strcmp(p, "chanmsg_sound")) {
               get_config_string(&sound[CHANMSG_SOUND], 1);

               } else if (! strcmp(p, "privmsg_sound")) {
                   get_config_string(&sound[PRIVMSG_SOUND], 1);

               } else if (! strcmp(p, "join_sound")) {
               get_config_string(&sound[JOIN_SOUND], 1);

               } else if (! strcmp(p, "part_sound")) {
               get_config_string(&sound[PART_SOUND], 1);
/*
               } else if (! strcmp(p, "FILELIST")) {
               read_file_list(f);

               } else if (! strcmp(p, "HOTLIST")) {
               read_hot_list(f);
*/
               } else {
               fprintf(stderr, "Invalid option '%s'\n", p);
               exit(1);
               }
   }
   fclose(f);
}


void write_config(void)
{
   FILE *f;
   SERVER *srv;
   SHAREDDIR *dir;
   AUTOCOMMAND *ac;

   if (! (f = fopen(rc_file, "w"))) {
               err_msg(strerror(errno));
               return;
   }

   fprintf(f, "username       %s\n", user_info.user_name);
   fprintf(f, "password       %s\n", user_info.password);
   fprintf(f, "email          %s\n", user_info.email);
   fprintf(f, "dataport       %d\n", user_info.data_port);
   fprintf(f, "linktype       %d\n", user_info.link_type);
   fprintf(f, "registered     %d\n", user_info.registered);
   fprintf(f, "\n");
   fprintf(f, "dldir          %s\n", init_dl_dir);

   fprintf(f, "uldirs         ");
   for (dir = shared_dirs; dir; dir = dir->next) {
               fprintf(f, "%s", dir->dir_name);
               if (dir->next)
               fprintf(f, ":");
   }
   fprintf(f, "\n\n");

   fprintf(f, "servers        ");
   for (srv = servers; srv; srv = srv->next) {
               fprintf(f, "%s:%04d:%d ",
                       srv->name, srv->port, srv->meta);
   }
   fprintf(f, "\n\n");

   fprintf(f, "minlink        %s\n", def_search.min_link);
   fprintf(f, "minfreq        %s\n", def_search.min_freq);
   fprintf(f, "minbitrate     %s\n", def_search.min_bitrate);
   fprintf(f, "maxfiles       %s\n", def_search.max_files);
   fprintf(f, "\n");
   fprintf(f, "showpath       %d\n", show_path);
   fprintf(f, "timeout        %d\n", time_out);
   fprintf(f, "\n");

   fprintf(f, "autocommands   ");
   for (ac = auto_commands; ac; ac = ac->next) {
               fprintf(f, "%s", ac->data);
               if (ac->next)
               fprintf(f, "; ");
   }

/*
   fprintf(f, "\n\n");
   fprintf(f, "FILELIST\n");
   save_file_list(f);
   fprintf(f, "\n");
   fprintf(f, "HOTLIST\n");
   save_hot_list(f);
*/
   fclose(f);
}


void config(int argc, char **argv)
{
   FILE *f;
   char *home_dir, *tmp;

   if ((tmp = getenv("HOME")))
               init_dl_dir = new_string(tmp);
       else
               init_dl_dir = new_string("c:\\");

   user_info.user_name = new_string("NewUser");
   user_info.password = new_string("password");
   user_info.email = new_string("[email protected]");
   user_info.data_port = 6699;
   user_info.link_type = 4;
   user_info.registered = 0;

   cur_search.artist = new_string("");
   cur_search.title = new_string("");
   cur_search.min_link = new_string("4");
   cur_search.min_freq = new_string("44100");
   cur_search.min_bitrate = new_string("128");
   cur_search.max_files = new_string("100");
   def_search.min_link = new_string(cur_search.min_link);
   def_search.min_freq = new_string(cur_search.min_freq);
   def_search.min_bitrate = new_string(cur_search.min_bitrate);
   def_search.max_files = new_string(cur_search.max_files);

   servers = (SERVER*)malloc(sizeof(SERVER));
   servers->name = new_string("bitchx.dimension6.com");
   servers->port = 8888;
   servers->meta = 0;
   servers->next = NULL;
   cur_server.name = new_string(servers->name);
   cur_server.port = servers->port;
   cur_server.meta = servers->meta;

   if (argc > 1)
               rc_file = new_string(argv[1]);
   else
               rc_file = new_string("connap.cfg");

   if ((f = fopen(rc_file, "r")))
               read_config(f);
}