/*
*  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 <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/Frame.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/Protocols.h>
#include <signal.h>

#include "main.h"
#include "config.h"
#include "configwin.h"
#include "chat.h"
#include "msgbox.h"
#include "command.h"
#include "connect.h"
#include "search.h"
#include "whois.h"
#include "shared.h"
#include "hotlist.h"
#include "input.h"
#include "info.h"
#include "fsbox.h"
#include "transfer.h"
#include "util.h"


#define XMNAP_VERSION "0.2.13"

String client;

XtAppContext appCon;

Pixmap napPix;

String linkStr[] = {
   "unknown",
   "14.4",
   "28.8",
   "33.6",
   "57.6",
   "64k ISDN",
   "128k ISDN",
   "Cable",
   "DSL",
   "T1",
   "T3+"
};

USERINFO userInfo;

SERVER *servers = NULL;
SERVER curServer;
String realSrvName = NULL;

int autoReconnect = 0;

int timeOut = 20;

String initDlDir;

Widget topLevel = NULL, mainBtn[6], mainLbl[6];
static Widget infoWin = NULL, infoText;
Widget statusLbl1, statusLbl2;
Widget curFocus = NULL, curWin =NULL;
int curWinType;

Pixmap mainPix[7], armPix[7];

char Buf[8192];

int showPath = 0;

static String fallbacks[] = {
   NULL
};


void FocusCB(Widget w, XtPointer clientData, XtPointer callData)
{
   curFocus = XtParent(w);
}


void DestroyWin(Widget w)
{
   XtDestroyWidget(w);
   curFocus = NULL;
}


static void InfoClearCB(Widget w, XtPointer clientData,
       XmPushButtonCallbackStruct *cbs)
{
   XmTextSetString(infoText, "");
}


static void InfoDeleteCB(Widget w, XtPointer clientData,
       XmAnyCallbackStruct *cbs)
{
   DestroyWin(infoWin);
   infoWin = NULL;
}


static void InfoWindow(void)
{
   Arg args[20];
   int n;
   Widget infoForm, clearBtn;

   infoWin = XtVaCreatePopupShell("miscInfo",
           topLevelShellWidgetClass, topLevel,
           XmNiconPixmap, napPix,
           NULL);

   infoForm = XtVaCreateManagedWidget("miscInfoForm",
           xmFormWidgetClass, infoWin,
           XmNmarginWidth, 6,
           XmNmarginHeight, 6,
           NULL);

   clearBtn = XtVaCreateManagedWidget("clearBtn",
           xmPushButtonWidgetClass, infoForm,
           XmNleftAttachment, XmATTACH_FORM,
           XmNleftOffset, 20,
           XmNbottomAttachment, XmATTACH_FORM,
           XmNbottomOffset, 8,
           NULL);

   n = 0;
   XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
   XtSetArg(args[n], XmNeditable, False); n++;
   XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
   XtSetArg(args[n], XmNbottomWidget, clearBtn); n++;
   XtSetArg(args[n], XmNbottomOffset, 8); n++;
   infoText = XmCreateScrolledText(infoForm, "miscInfoText", args, n);

   XtManageChild(infoText);

   XtAddCallback(infoForm, XmNfocusCallback,
           (XtCallbackProc)FocusCB, NULL);

   XtAddCallback(clearBtn, XmNactivateCallback,
           (XtCallbackProc)InfoClearCB, NULL);

   XmAddWMProtocolCallback(infoWin,
           XmInternAtom(XtDisplay(infoWin), "WM_DELETE_WINDOW", False),
           (XtCallbackProc)InfoDeleteCB, NULL);

   XtVaSetValues(infoForm, XmNinitialFocus, XtParent(infoText),
           NULL);
   XtPopup(infoWin, XtGrabNone);
}


void ShowMiscInfo(String text, int mode)
{
   String newLines[2] = {"\n\n", "\n"};
   String s;
   XmTextPosition pos;

   if (! infoWin)
       InfoWindow();

   if ((pos = XmTextGetLastPosition(infoText))) {
       XmTextInsert(infoText, pos, newLines[mode]);
       pos += strlen(newLines[mode]);
   }

   XmTextInsert(infoText, pos, text);
   pos += strlen(text);

   if (pos > 10000) {
       s = XmTextGetString(infoText);
       XmTextSetString(infoText, s + 1000);
       XtFree(s);
   }

   XmTextSetInsertionPosition(infoText,
           XmTextGetLastPosition(infoText));
}


static void MainBtnCB(Widget w, XtPointer clientData,
       XmPushButtonCallbackStruct *cbs)
{
   String nick, tmp;

   if (w == mainBtn[0]) {
       if (! srvConn) {
           if (! curServer.name) {
               ErrMsg("Define servers first");
               return;
           }
           tmp = XtNewString(curServer.name);
           Connect(tmp, curServer.port, curServer.meta, 1);
           XtFree(tmp);
       } else {
           Disconnect("");
       }
   } else if (w == mainBtn[1]) {
       if (! srvConn)
           return;
       Search();
   } else if (w == mainBtn[2]) {
       if (! srvConn)
           return;
       nick = GetInput("Browse", "", 30);
       if (strlen(nick))
           Browse(nick);
   } else if (w == mainBtn[3]) {
       if (! srvConn)
           return;
       nick = GetInput("Whois", "", 30);
       if (strlen(nick))
           Whois(nick);
   } else if (w == mainBtn[4]) {
       ConfigWin(1);
   } else {
       Quit();
   }
}


static void MainEntryCB(Widget w, XtPointer clientData,
       XmAnyCallbackStruct *cbs)
{
   String s;

   s = XmTextFieldGetString(w);
   XmTextFieldSetString(w, "");
   CmdParse(s);
   XtFree(s);
}


static void MainDeleteCB(Widget w, XtPointer clientData,
       XmAnyCallbackStruct *cbs)
{
   Quit();
}


static void MainActions(Widget w, XEvent *ev, String *params,
       int *numParams)
{
   if (! strcmp(params[0], "connect")) {
       if (! srvConn)
           XtCallCallbacks(mainBtn[0], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "disc")) {
       if (srvConn)
           XtCallCallbacks(mainBtn[0], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "search")) {
       XtCallCallbacks(mainBtn[1], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "browse")) {
       XtCallCallbacks(mainBtn[2], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "whois")) {
       XtCallCallbacks(mainBtn[3], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "config")) {
       XtCallCallbacks(mainBtn[4], XmNactivateCallback, NULL);
   } else if (! strcmp(params[0], "quit")) {
       XtCallCallbacks(mainBtn[5], XmNactivateCallback, NULL);
   }
}


static void InitActions()
{
   XtActionsRec actionTable[] = {
       {"Main", (XtActionProc)MainActions},
       {"Chat", (XtActionProc)ChatActions},
   };
   XtAppAddActions(appCon, actionTable, 3);
}


static void Init(int argc, char **argv)
{
   signal(SIGPIPE, SIG_IGN);
   Config(argc, argv);
   SetDataPort(userInfo.dataPort, 1);
}


void Quit(void)
{
   exit(0);
}


int main(int argc, char **argv)
{
   Widget mainForm, btnFrame, rowCol, form, cmdLine;
   String pixFile[7] = {"disconnect", "search", "browse", "whois",
                       "config", "quit", "connect"};
   String btnName[6] = {"connect", "search", "browse", "whois",
                        "config", "quit"};
   String labelName[6] = {"connectLbl", "searchLbl", "browseLbl",
                          "whoisLbl", "configLbl", "quitLbl"};
   char tmp[128];
   int n, i;
   Arg args[20];
   Pixel bg, armColor;

   client = XtMalloc(sizeof("XmNap v") + sizeof(XMNAP_VERSION) + 1);
   sprintf(client, "XmNap v%s", XMNAP_VERSION);

   topLevel = XtVaAppInitialize(&appCon, "XmNap", NULL, 0,
           &argc, argv, fallbacks,
           XmNtitle, client,
           NULL);

   InitActions();

   napPix = XmGetPixmap(XtScreen(topLevel), "xmnap/xmnap.xpm", 0, 0);

   XtVaSetValues(topLevel, XmNiconPixmap, napPix, NULL);

   mainForm = XtVaCreateManagedWidget("form",
           xmFormWidgetClass, topLevel,
           XmNmarginWidth, 0,
           XmNmarginHeight, 0,
           XmNshadowThickness, 0,
           NULL);

   cmdLine = XtVaCreateManagedWidget("cmdLine",
           xmTextFieldWidgetClass, mainForm,
           XmNleftAttachment, XmATTACH_FORM,
           XmNleftOffset, 5,
           XmNrightAttachment, XmATTACH_FORM,
           XmNrightOffset, 5,
           XmNbottomAttachment, XmATTACH_FORM,
           XmNbottomOffset, 5,
           NULL);

   btnFrame = XtVaCreateManagedWidget("btnFrame",
           xmFrameWidgetClass, mainForm,
           XmNshadowType, XmSHADOW_OUT,
           XmNshadowThickness, 2,
           XmNtopAttachment, XmATTACH_FORM,
           XmNleftAttachment, XmATTACH_FORM,
           XmNrightAttachment, XmATTACH_FORM,
           NULL);

   rowCol = XtVaCreateManagedWidget("rowCol",
           xmRowColumnWidgetClass, btnFrame,
           XmNorientation, XmHORIZONTAL,
           XmNpacking, XmPACK_COLUMN,
           XmNspacing, 12,
           XmNmarginWidth, 12,
           XmNmarginHeight, 6,
           NULL);

   for (i = 0; i < 6; i++) {
       form = XtVaCreateWidget("form",
               xmFormWidgetClass, rowCol,
               NULL);

       mainBtn[i] = XtVaCreateWidget(btnName[i],
               xmPushButtonWidgetClass, form,
               XmNlabelType, XmPIXMAP,
               XmNmarginWidth, 5,
               XmNmarginHeight, 5,
               XmNshadowThickness, 0,
               XmNtopAttachment, XmATTACH_FORM,
               XmNleftAttachment, XmATTACH_FORM,
               XmNrightAttachment, XmATTACH_FORM,
               NULL);

       XtAddCallback(mainBtn[i], XmNactivateCallback,
               (XtCallbackProc)MainBtnCB, NULL);

       mainLbl[i] = XtVaCreateWidget(labelName[i],
               xmLabelWidgetClass, form,
               XmNrecomputeSize, False,
               XmNmarginWidth, 0,
               XmNmarginHeight, 1,
               XmNtopAttachment, XmATTACH_WIDGET,
               XmNtopWidget, mainBtn[i],
               XmNtopOffset, 5,
               XmNbottomAttachment, XmATTACH_FORM,
               XmNleftAttachment, XmATTACH_FORM,
               XmNrightAttachment, XmATTACH_FORM,
               NULL);

       XtManageChild(mainBtn[i]);
       XtManageChild(mainLbl[i]);
       XtManageChild(form);
   }

   XtVaGetValues(mainBtn[0], XmNbackground, &bg, NULL);
   XtVaGetValues(mainBtn[0], XmNarmColor, &armColor, NULL);
   for (i = 0; i < 7; i++) {
       sprintf(tmp, "xmnap/%s.xpm", pixFile[i]);
       mainPix[i] = XmGetPixmap(XtScreen(topLevel), tmp, 0, bg);
       sprintf(tmp, "xmnap/%s_arm.xpm", pixFile[i]);
       armPix[i] = XmGetPixmap(XtScreen(topLevel), tmp, 0, armColor);
       if (i < 6) {
           XtVaSetValues(mainBtn[i],
                   XmNlabelPixmap, mainPix[i],
                   XmNarmPixmap, armPix[i],
                   NULL);
       }
   }

   statusLbl1 = XtVaCreateManagedWidget("statusLbl",
           xmLabelWidgetClass, mainForm,
           XmNmarginWidth, 20,
           XmNmarginHeight, 20,
           XmNtopAttachment, XmATTACH_WIDGET,
           XmNtopWidget, btnFrame,
           XmNleftAttachment, XmATTACH_FORM,
           XmNbottomAttachment, XmATTACH_WIDGET,
           XmNbottomWidget, cmdLine,
           NULL);

   statusLbl2 = XtVaCreateManagedWidget("statusLbl",
           xmLabelWidgetClass, mainForm,
           XmNmarginWidth, 20,
           XmNmarginHeight, 20,
           XmNtopAttachment, XmATTACH_WIDGET,
           XmNtopWidget, btnFrame,
           XmNrightAttachment, XmATTACH_FORM,
           XmNbottomAttachment, XmATTACH_WIDGET,
           XmNbottomWidget, cmdLine,
           NULL);

   n = 0;
   XtSetArg(args[n], XmNinitialFocus, cmdLine); n++;
   XtSetValues(mainForm, args, n);

   XtAddCallback(mainForm, XmNfocusCallback,
           (XtCallbackProc)FocusCB, NULL);

   XtAddCallback(cmdLine, XmNactivateCallback,
           (XtCallbackProc)MainEntryCB, NULL);

   XmAddWMProtocolCallback(topLevel,
           XmInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW", False),
           (XtCallbackProc)MainDeleteCB, NULL);

   InfoWindow();

   XtRealizeWidget(topLevel);
   ForceWindow(topLevel);

   Init(argc, argv);

   XtAppMainLoop(appCon);
   return 0;
}