/*
*  XmNap  A Motif napster client
*
*  Copyright (C) 2000 Mats Peterson
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; see the file COPYING.  If not, write to
*  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
*  Boston, MA 02111-1307, USA.
*
*  Please send any comments/bug reports to
*  [email protected]  (Mats Peterson)
*/

#include <Xm/Xm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>

#include "main.h"
#include "command.h"
#include "connect.h"
#include "search.h"
#include "config.h"
#include "configwin.h"
#include "shared.h"
#include "hotlist.h"
#include "msgbox.h"
#ifdef USE_SOUND
#include "sound.h"
#endif
#include "util.h"


static String rcFile;


static void GetConfigString(String *s, int acceptEmpty)
{
   String p;

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

empty:
   if (acceptEmpty) {
       XtFree(*s);
       *s = XtNewString("");
   } else {
       fprintf(stderr, "Missing configuration value in .xmnaprc\n");
       exit(1);
   }
}


static void GetConfigInt(int *val)
{
   String 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 .xmnaprc\n");
   exit(1);
}


static void GetConfigServers(void)
{
   String p, tmp, name, portString, metaString;
   SERVER *newServer, *prevServer = NULL;

   while (servers) {
       XtFree(servers->name);
       p = (String)servers;
       servers = servers->next;
       XtFree(p);
   }

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

       tmp = XtNewString(p);

       if (! SplitServer(tmp, &name, &portString, &metaString)) {
           fprintf(stderr, "Invalid server format in .xmnaprc\n");
           exit(1);
       }

       newServer = XtNew(SERVER);
       newServer->name = XtNewString(name);
       newServer->port = atoi(portString);
       newServer->meta = atoi(metaString);
       newServer->next = NULL;

       if (! servers)
           servers = newServer;
       if (prevServer)
           prevServer->next = newServer;

       prevServer = newServer;
       XtFree(tmp);
   }

   if (! servers)
       return;
   if (curServer.name)
       XtFree(curServer.name);
   curServer.name = XtNewString(servers->name);
   curServer.port = servers->port;
   curServer.meta = servers->meta;
}


static void GetConfigAutoCommands(void)
{
   String p, tmp;
   AUTOCOMMAND *newCommand, *prevCommand = NULL;

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

       newCommand = XtNew(AUTOCOMMAND);
       newCommand->data = XtNewString(tmp);
       newCommand->next = NULL;

       if (! autoCommands)
           autoCommands = newCommand;

       if (prevCommand)
           prevCommand->next = newCommand;

       prevCommand = newCommand;
       XtFree(tmp);
   }
}


static void GetConfigSharedDirs(void)
{
   String p;
   SHAREDDIR *newDir, *prevDir = NULL;

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

       newDir = XtNew(SHAREDDIR);
       newDir->dirName = XtNewString(p);
       newDir->next = NULL;

       if (! sharedDirs)
           sharedDirs = newDir;
       if (prevDir)
           prevDir->next = newDir;

       prevDir = newDir;
   }
}


static void ReadConfig(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")) {
           GetConfigString(&userInfo.userName, 0);

       } else if (! strcmp(p, "password")) {
           GetConfigString(&userInfo.passWord, 0);

       } else if (! strcmp(p, "email")) {
           GetConfigString(&userInfo.eMail, 0);

       } else if (! strcmp(p, "dataport")) {
           GetConfigInt(&userInfo.dataPort);

       } else if (! strcmp(p, "linktype")) {
           GetConfigInt(&userInfo.linkType);

       } else if (! strcmp(p, "registered")) {
           GetConfigInt(&userInfo.registered);

       } else if (! strcmp(p, "dldir")) {
           GetConfigString(&initDlDir, 0);

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

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

       } else if (! strcmp(p, "minlink")) {
           GetConfigString(&search.minLink, 0);
           defSearch.minLink = XtNewString(search.minLink);

       } else if (! strcmp(p, "minfreq")) {
           GetConfigString(&search.minFreq, 0);
           defSearch.minFreq = XtNewString(search.minFreq);

       } else if (! strcmp(p, "minbitrate")) {
           GetConfigString(&search.minBitrate, 0);
           defSearch.minBitrate = XtNewString(search.minBitrate);

       } else if (! strcmp(p, "maxfiles")) {
           GetConfigString(&search.maxFiles, 0);
           defSearch.maxFiles = XtNewString(search.maxFiles);

       } else if (! strcmp(p, "autoreconnect")) {
           GetConfigInt(&autoReconnect);

       } else if (! strcmp(p, "showpath")) {
           GetConfigInt(&showPath);

       } else if (! strcmp(p, "timeout")) {
           GetConfigInt(&timeOut);

       } else if (! strcmp(p, "reconntimeout")) {
           GetConfigInt(&reconnTimeOut);

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

       } else if (! strcmp(p, "chanmsg_sound")) {
#ifdef USE_SOUND
           GetConfigString(&sound[CHANMSG_SOUND], 1);
#endif
       } else if (! strcmp(p, "privmsg_sound")) {
#ifdef USE_SOUND
           GetConfigString(&sound[PRIVMSG_SOUND], 1);
#endif
       } else if (! strcmp(p, "join_sound")) {
#ifdef USE_SOUND
           GetConfigString(&sound[JOIN_SOUND], 1);
#endif
       } else if (! strcmp(p, "part_sound")) {
#ifdef USE_SOUND
           GetConfigString(&sound[PART_SOUND], 1);
#endif
       } else if (! strcmp(p, "FILELIST")) {
           ReadFileList(f);

       } else if (! strcmp(p, "HOTLIST")) {
           ReadHotList(f);

       } else {
           fprintf(stderr, "Invalid option '%s'\n", p);
           exit(1);
       }
   }
   fclose(f);
}


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

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

   fprintf(f, "username       %s\n", userInfo.userName);
   fprintf(f, "password       %s\n", userInfo.passWord);
   fprintf(f, "email          %s\n", userInfo.eMail);
   fprintf(f, "dataport       %d\n", userInfo.dataPort);
   fprintf(f, "linktype       %d\n", userInfo.linkType);
   fprintf(f, "registered     %d\n", userInfo.registered);
   fprintf(f, "\n");
   fprintf(f, "dldir          %s\n", initDlDir);

   fprintf(f, "uldirs         ");
   for (dir = sharedDirs; dir; dir = dir->next) {
       fprintf(f, "%s", dir->dirName);
       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", defSearch.minLink);
   fprintf(f, "minfreq        %s\n", defSearch.minFreq);
   fprintf(f, "minbitrate     %s\n", defSearch.minBitrate);
   fprintf(f, "maxfiles       %s\n", defSearch.maxFiles);
   fprintf(f, "\n");
   fprintf(f, "autoreconnect  %d\n", autoReconnect);
   fprintf(f, "showpath       %d\n", showPath);
   fprintf(f, "timeout        %d\n", timeOut);
   fprintf(f, "reconntimeout  %d\n", reconnTimeOut);
   fprintf(f, "\n");

#ifdef USE_SOUND
   fprintf(f, "chanmsg_sound  %s\n", sound[CHANMSG_SOUND]);
   fprintf(f, "privmsg_sound  %s\n", sound[PRIVMSG_SOUND]);
   fprintf(f, "join_sound     %s\n", sound[JOIN_SOUND]);
   fprintf(f, "part_sound     %s\n", sound[PART_SOUND]);
   fprintf(f, "\n");
#endif

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

   fprintf(f, "\n\n");
   fprintf(f, "FILELIST\n");
   SaveFileList(f);
   fprintf(f, "\n");
   fprintf(f, "HOTLIST\n");
   SaveHotList(f);
   fclose(f);

   if (chmod(rcFile, 0600) == -1)
       ErrMsg(strerror(errno));
}


void Config(int argc, char **argv)
{
   FILE *f;
   String homeDir;
#ifdef USE_SOUND
   int i;
#endif

   initDlDir = XtNewString(getenv("HOME"));

   userInfo.userName = XtNewString("");
   userInfo.passWord = XtNewString("");
   userInfo.eMail = XtNewString("[email protected]");
   userInfo.dataPort = 6699;
   userInfo.linkType = 4;
   userInfo.registered = 0;

   search.artist = XtNewString("");
   search.title = XtNewString("");
   search.minLink = XtNewString("4");
   search.minFreq = XtNewString("44100");
   search.minBitrate = XtNewString("128");
   search.maxFiles = XtNewString("100");
   defSearch.minLink = XtNewString(search.minLink);
   defSearch.minFreq = XtNewString(search.minFreq);
   defSearch.minBitrate = XtNewString(search.minBitrate);
   defSearch.maxFiles = XtNewString(search.maxFiles);

   servers = XtNew(SERVER);
   servers->name = XtNewString("bitchx.dimension6.com");
   servers->port = 8888;
   servers->meta = 0;
   servers->next = NULL;
   curServer.name = XtNewString(servers->name);
   curServer.port = servers->port;
   curServer.meta = servers->meta;

#ifdef USE_SOUND
   for (i = 0; i < NUM_SOUNDS; i++)
       sound[i] = XtNewString("");
#endif

   if (argc > 1)
       rcFile = XtNewString(argv[1]);
   else {
       homeDir = getenv("HOME");
       rcFile = XtMalloc(strlen(homeDir) + sizeof("/.xmnaprc") + 1);
       sprintf(rcFile, "%s/.xmnaprc", homeDir);
   }

   if ((f = fopen(rcFile, "r")))
       ReadConfig(f);
   else {
       ConfigWin(1);
   }
}