/*
*  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/MessageB.h>
#include <Xm/List.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "main.h"
#include "connect.h"
#include "transfer.h"
#include "message.h"
#include "msgbox.h"
#include "listwin.h"
#include "search.h"
#include "transfer.h"
#include "searchdlg.h"
#include "util.h"


SEARCH search, defSearch;
SRESULT *resData = NULL;
SRESULT *prevResult = NULL;


static Widget listWin = NULL;


void DestroyResultsWin(void)
{
   if (listWin) {
       DestroyWin(XtParent(listWin));
       listWin = NULL;
   }
}


void Search2(void)
{
   String p;
   String tmp = XtCalloc(4096, 1);

   if ((strlen(search.artist))) {
       strcat(tmp, "FILENAME CONTAINS \"");
       strcat(tmp, search.artist);
       strcat(tmp, "\"");
   }

   strcat(tmp, " MAX_RESULTS ");
   strcat(tmp, search.maxFiles);

   if ((strlen(search.title))) {
       strcat(tmp, " FILENAME CONTAINS \"");
       strcat(tmp, search.title);
       strcat(tmp, "\"");
   }

   if ((strlen(search.minLink))) {
       strcat(tmp, " LINESPEED \"AT LEAST\" ");
       strcat(tmp, search.minLink);
   }

   if ((strlen(search.minBitrate))) {
       strcat(tmp, " BITRATE \"AT LEAST\" \"");
       strcat(tmp, search.minBitrate);
       strcat(tmp, "\"");
   }

   if ((strlen(search.minFreq))) {
       strcat(tmp, " FREQ \"AT LEAST\" \"");
       strcat(tmp, search.minFreq);
       strcat(tmp, "\"");
   }

   while (resData) {
       XtFree(resData->data);
       p = (String)resData;
       resData = resData->next;
       XtFree(p);
   }
   resData = NULL;
   prevResult = NULL;

   if (SendMsg(MSG_CLIENT_SEARCH, tmp))
       Disconnect(strerror(errno));

   XtFree(tmp);
}


void Search(void)
{
   SearchDlg();
}


void Browse(String nick)
{
   String p;

   while (resData) {
       XtFree(resData->data);
       p = (String)resData;
       resData = resData->next;
       XtFree(p);
   }
   resData = NULL;
   prevResult = NULL;

   if (SendMsg(MSG_CLIENT_BROWSE, nick))
       Disconnect(strerror(errno));
}


void AddResult(String s, int mode)
{
   SRESULT *newResult, *resPtr, *prevPtr = NULL;
   String path, newPath;
   String fileName, newFileName;
   String tmp, tmp2 = XtMalloc(1024);

   newResult = XtNew(SRESULT);
   newResult->data = XtNewString(s);

   tmp = XtNewString(s);

   if (mode) {
       (void)strtok(tmp, " ");
       newPath = strtok(NULL, "\"");
   } else {
       newPath = strtok(tmp, "\"");
   }
   newFileName = GetFileTail(newPath);

   for (resPtr = resData; resPtr; resPtr = resPtr->next) {
       strcpy(tmp2, resPtr->data);
       if (mode) {
           (void)strtok(tmp2, " ");
           path = strtok(NULL, "\"");
       } else {
           path = strtok(tmp2, "\"");
       }

       fileName = GetFileTail(path);

       if (strcasecmp(fileName, newFileName) > 0) {
           XtFree(fileName);
           break;
       }

       XtFree(fileName);
       prevPtr = resPtr;
   }

   if (prevPtr) {
       newResult->next = prevPtr->next;
       prevPtr->next = newResult;
   } else {
       newResult->next = resData;
       resData = newResult;
   }

   XtFree(newFileName);
   XtFree(tmp);
   XtFree(tmp2);
}


static void ResListDlCB(XtPointer clientData, XtIntervalId *id)
{
   int *dlData = (int*)clientData;
   int pos = dlData[0], mode = dlData[1];

   XtFree((char*)dlData);
   Download(pos, mode);
}


static void ResListCB(Widget w, XtPointer clientData,
       XmListCallbackStruct *cbs)
{
   Widget list;
   int mode = (int)clientData;
   int *pos;
   int *dlData;

   switch (cbs->reason) {
       case XmCR_OK:
           list = XtNameToWidget(w, "ItemsListSW.ItemsList");
           XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
           dlData = (int*)XtMalloc(2 * sizeof(int));
           dlData[0] = (*pos) - 1;
           dlData[1] = mode;
           XtAppAddTimeOut(appCon, 10, ResListDlCB, (XtPointer)dlData);
           break;
       case XmCR_CANCEL:
       case XmCR_PROTOCOLS:
           DestroyResultsWin();
           break;
   }
}


void ShowResults(int mode)
{
   XmString *str;
   String listName[2] = {"searchList", "browseList"};
   SRESULT *res;
   String tmp, fmtStr = XtMalloc(50), resStr = XtMalloc(4096);
   String fileName, size, freq, bitrate, nick, link;
   char fmtTime[20];
   int fnLen, nickLen, time;
   int i, numFiles;

   if (! resData) {
       InfoMsg("No files found");
       goto exit;
   }

   DestroyResultsWin();

   listWin = ListWin(listName[mode], (XtCallbackProc)ResListCB,
           (XtPointer)mode);

   /* Calculate longest lengths of filename and nick */
   for (fnLen = 0, nickLen = 0, numFiles = 0, res = resData;
        res; numFiles++, res = res->next) {
       tmp = XtNewString(res->data);
       if (mode) {
           (void)strtok(tmp, " ");
           fileName = strtok(NULL, "\"");
       } else {
           fileName = strtok(tmp, "\"");
           (void)strtok(NULL, " ");
           (void)strtok(NULL, " ");
           (void)strtok(NULL, " ");
           (void)strtok(NULL, " ");
           (void)strtok(NULL, " ");
           nick = strtok(NULL, " ");
           if (strlen(nick) > nickLen)
               nickLen = strlen(nick);
       }

       if (! showPath)
           fileName = GetFileTail(fileName);

       if (strlen(fileName) > fnLen)
           fnLen = strlen(fileName);

       if (! showPath)
           XtFree(fileName);
       XtFree(tmp);
   }
   fnLen += 3;
   nickLen += 3;

   str = (XmString*)XtMalloc(numFiles * sizeof(XmString));
   for (i = 0, res = resData; i < numFiles; i++, res = res->next) {
       tmp = XtNewString(res->data);

       if (mode) {
           /* no nick display */
           (void)strtok(tmp, " ");
           fileName = strtok(NULL, "\"");
           if (! showPath)
               fileName = GetFileTail(fileName);
           /* no md5 display */
           (void)strtok(NULL, " ");
           size = strtok(NULL, " ");
           bitrate = strtok(NULL, " ");
           freq = strtok(NULL, " ");
           time = atoi(strtok(NULL, " "));
           sprintf(fmtTime, "%2d:%02d", time / 60, time % 60);
           sprintf(fmtStr, "%%-%ds%%-12s%%-7s%%-9s%%-9s", fnLen);
           sprintf(resStr, fmtStr, fileName, size, bitrate, freq, fmtTime);
       } else {
           fileName = strtok(tmp, "\"");
           if (! showPath)
               fileName = GetFileTail(fileName);
           /* no md5 display */
           (void)strtok(NULL, " ");
           size = strtok(NULL, " ");
           bitrate = strtok(NULL, " ");
           freq = strtok(NULL, " ");
           time = atoi(strtok(NULL, " "));
           sprintf(fmtTime, "%2d:%02d", time / 60, time % 60);
           nick = strtok(NULL, " ");
           /* no ip display */
           (void)strtok(NULL, " ");
           link = linkStr[atoi(strtok(NULL, " "))];

           sprintf(fmtStr, "%%-%ds%%-12s%%-7s%%-9s%%-9s%%-%ds%%s  ",
                   fnLen, nickLen);
           sprintf(resStr, fmtStr, fileName, size, bitrate, freq,
                   fmtTime, nick, link);
       }

       str[i] = XmStringCreateLocalized(resStr);
       if (! showPath)
           XtFree(fileName);
       XtFree(tmp);
   }

   XtVaSetValues(listWin,
           XmNlistItems, str,
           XmNlistItemCount, numFiles,
           NULL);

   for (i = 0; i < numFiles; i++)
       XmStringFree (str[i]);
   XtFree((String)str);

exit:
   XtFree(fmtStr);
   XtFree(resStr);
}