/*
*  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 <unistd.h>
#include <errno.h>

#include "main.h"
#include "message.h"
#include "connect.h"
#include "command.h"
#include "chat.h"
#include "search.h"
#include "shared.h"
#include "msgbox.h"
#include "chnlist.h"
#include "hotlist.h"
#include "linklist.h"
#include "banlist.h"
#include "ullist.h"
#include "netutil.h"

XtInputId srvCB;

int srvSock, srvPort;
int srvConn = 0;

int reconnTimeOut = 15;

static int reconnId = 0;


static String Redirect(String metaServer, int metaPort, int first,
       int *connRet)
{
   int i, r, metaSock;
   String tmp = XtMalloc(4096);
   char c;

   sprintf(tmp, "Trying metaserver %s...", metaServer);
   if (first)
       SimpleMsg(tmp);
   else
       ShowMiscInfo(tmp, 0);

   if ((*connRet = ConnSock(metaServer, metaPort, &metaSock)))
       goto error;

   memset(tmp, 0, strlen(tmp));
   i = 0;

   while (1) {
       while (((r = read(metaSock, &c, 1)) == -1) && (errno == EAGAIN))
           usleep(1000);
       if (r <= 0) {
           if (r == -1) {
               close(metaSock);
               ErrMsg(strerror(r));
               goto error;
           }
           break;
       }
       if (c == '\n')
           break;
       tmp[i++] = c;
   }

   close(metaSock);
   if (first)
       SimpleMsgRemove();
   return tmp;

error:
   XtFree(tmp);
   return NULL;
}


void Connect(String server, int port, int meta, int first)
{
   char loginMsg[256];
   int realPort;
   String tmp, srvString;
   XmString xms;
   static int connInProgress = 0;
   int connRet;

   if (srvConn)
       return;

   if (connInProgress) {
       ErrMsg("Connect already in progress");
       return;
   }
   connInProgress = 1;

   if (reconnId) {
       XtRemoveTimeOut(reconnId);
       reconnId = 0;
   }

   if (curServer.name)
       XtFree(curServer.name);
   curServer.name = XtNewString(server);
   curServer.port = port;
   curServer.meta = meta;

   if (realSrvName) {
       XtFree(realSrvName);
       realSrvName = NULL;
   }

   if (meta) {
       if (! (srvString = Redirect(server, port, first, &connRet)))
           goto error;
       if ((! strlen(srvString)) || (! strchr(srvString, ':'))) {
           ErrMsg("Got invalid string from metaserver");
           XtFree(srvString);
           goto error;
       }
       tmp = strtok(srvString, ":");
       realSrvName = XtNewString(tmp);
       realPort = atoi(strtok(NULL, "\0"));
       XtFree(srvString);
   } else {
       realSrvName = XtNewString(server);
       realPort = port;
   }

   tmp = XtMalloc(sizeof("Connecting to ") +
           strlen(realSrvName) + sizeof("...") + 1);
   sprintf(tmp, "Connecting to %s...", realSrvName);
   if (first)
       SimpleMsg(tmp);
   else
       ShowMiscInfo(tmp, 0);
   XtFree(tmp);

   if ((connRet = ConnSock(realSrvName, realPort, &srvSock)))
       goto error;

   srvCB = XtAppAddInput(appCon, srvSock, (XtPointer)XtInputReadMask,
           (XtInputCallbackProc)GetMsg, NULL);

   if (! userInfo.registered) {
       if (SendMsg(MSG_CLIENT_REGISTER, userInfo.userName)) {
           Disconnect(strerror(errno));
           goto error;
       }
   } else {
       sprintf(loginMsg, "%s %s %04d \"%s\" %d",
               userInfo.userName, userInfo.passWord,
               userInfo.dataPort, client, userInfo.linkType);

       if (SendMsg(MSG_CLIENT_LOGIN, loginMsg)) {
           Disconnect(strerror(errno));
           goto error;
       }
   }

   XtVaSetValues(mainBtn[0],
           XmNlabelPixmap, mainPix[6],
           XmNarmPixmap, armPix[6],
           NULL);

   xms = XmStringCreateLocalized("Disc");
   XtVaSetValues(mainLbl[0], XmNlabelString, xms, NULL);
   XmStringFree(xms);

   srvConn = 1;

error:
   connInProgress = 0;
   if (first)
       SimpleMsgRemove();
#ifdef AUTORECONNECT_ON_REFUSED
   if (connRet == -2)
       WaitReconnect();
#endif
}


void DoLoginStuff(XtPointer closure, XtIntervalId *id)
{
   NotifySharedFiles();
   SendHotList();
   SendAutoCommands();
}


static void Reconnect(XtPointer clientData, XtInputId *id)
{
   String tmp;

   tmp = XtNewString(curServer.name);
   Connect(tmp, curServer.port, curServer.meta, 0);
   XtFree(tmp);
}


void WaitReconnect(void)
{
   Disconnect("");
   ShowMiscInfo("Waiting...", 0);
   reconnId = XtAppAddTimeOut(appCon, reconnTimeOut * 1000,
           (XtTimerCallbackProc)Reconnect, (XtPointer)NULL);
}


void Disconnect(String err)
{
   XmString xms;

   if (! srvConn)
       return;

   if (strlen(err))
       ErrMsg(err);

   PartAllChannels();
   CloseAllPrivs();
   ClearOnLineList();

   DestroyResultsWin();
   DestroyLinksWin();
   DestroyUlListWin();
   DestroyChnListWin();
   DestroyBanListWin();
   DestroyOnLineListWin();

   XtRemoveInput(srvCB);
   close(srvSock);

   XtVaSetValues(mainBtn[0],
           XmNlabelPixmap, mainPix[0],
           XmNarmPixmap, armPix[0],
           NULL);

   xms = XmStringCreateLocalized("Connect");
   XtVaSetValues(mainLbl[0], XmNlabelString, xms, NULL);
   XmStringFree(xms);

   xms = XmStringCreateLocalized("");
   XtVaSetValues(statusLbl1, XmNlabelString, xms, NULL);
   XtVaSetValues(statusLbl2, XmNlabelString, xms, NULL);
   XmStringFree(xms);

   srvConn = 0;
}