/*

STRICQ - An Amiga, MUI Based, ICQ Clone.
Copyright (C) 1998-2000 Douglas F. McLaughlin

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; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Douglas F. McLaughlin - stricq@owlnet.net

*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <libraries/icq.h>

#include <proto/asyncio.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/miami.h>
#include <proto/utility.h>

#include <rexx/storage.h>

#include "STRICQMUI.h"

#include <proto/socket.h>

#define ICQRC "ICQRC"


LONG __asm RxStatus(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxGetContact(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxSendMessage(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxWinControl(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxAddFile(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxFileDirect(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxGetVersion(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxDeleteUIN(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxGetFiles(REG(a2) APTR, REG(a1) ULONG *);
LONG __asm RxAcceptChatFile(REG(a2) APTR, REG(a1) ULONG *);

extern BOOL CreateUserWin(ULONG);
extern struct Contact *GetContact(ULONG);
extern char *FindCountryName(UWORD);
extern ULONG GetSize(struct FileList *);
extern struct ColorText *GetStatus(ULONG);
extern void SendAMessage(APTR, ULONG, char *, UWORD, UBYTE, int);
extern void __asm SendFileSend(REG(a2) APTR);
extern LONG __asm SetFileSendStats(REG(a2) APTR);
extern BOOL StartChat(struct Contact *, BOOL);
extern BOOL StartFileXFer(struct Contact *, BOOL);
extern void DeleteUIN(ULONG);
extern void __asm Accept(REG(a2) APTR);
extern void __asm Refuse(REG(a2) APTR);


extern BOOL Online, ARexx;

extern char version_string[], *Statii[];

extern ULONG AsyncBuf;

extern struct ObjApp *app;


LONG __asm RxStatus(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL getstat, all;

char *c, *newstat, *newvar, var[20], val[10];

LONG index;

struct RexxMsg *rxmsg = NULL;

newstat = (char *)*array; array++;
getstat = *array; array++;
all     = *array; array++;
newvar  = (char *)*array;

if (!newvar) newvar = ICQRC;
else for(c = newvar; *c; c++) *c = ToUpper(*c);

get(obj,MUIA_Application_RexxMsg,&rxmsg);

if (all) {
  sprintf(val,"%d",NUM_STATUS);
  SetRexxVar((struct Message *)rxmsg,newvar,val,strlen(val));
  for(index = 0; index < NUM_STATUS; index++) {
    sprintf(var,"%s.%d",newvar,index);
    SetRexxVar((struct Message *)rxmsg,var,Statii[index],strlen(Statii[index]));
  }
  return(0);
}

if (getstat) {
  get(app->CY_MyStatus,MUIA_Cycle_Active,&index);
  if (index < NUM_STATUS-1 && !Online) index = NUM_STATUS-1;
  SetRexxVar((struct Message *)rxmsg,newvar,Statii[index],strlen(Statii[index]));
}

if (newstat) {
  for(c = newstat; *c; c++) if (*c == '_') *c = ' ';
  for(index = 0; index < NUM_STATUS; index++) {
    if (!stricmp(newstat,Statii[index])) {
      set(app->CY_MyStatus,MUIA_Cycle_Active,index);
      break;
    }
  }
  if (index == NUM_STATUS) return(5);
}

return(0);

}


LONG __asm RxGetContact(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL total, sel;

char *c, *uinstr, *entrystr, *newvar, var[50], val[512], *val2;

ULONG uin, entry, entries;

struct ColorText *ct;
struct Contact   *user;
struct RexxMsg   *rxmsg = NULL;

uinstr   = (char *)*array; array++;
entrystr = (char *)*array; array++;
sel      = *array; array++;
total    = *array; array++;
newvar   = (char *)*array;

if (uinstr)   StrToLong(uinstr,(LONG *)&uin);
if (entrystr) StrToLong(entrystr,(LONG *)&entry);

get(obj,MUIA_Application_RexxMsg,&rxmsg);

if (!newvar) newvar = ICQRC;
else for(c = newvar; *c; c++) *c = ToUpper(*c);

get(app->LV_OfflineList,MUIA_NList_Entries,&entries);

if (total) {
  sprintf(val,"%ld",entries);
  SetRexxVar((struct Message *)rxmsg,newvar,val,strlen(val));
  return(0);
}

if (uinstr) {
  if (!(user = GetContact(uin))) return(5);
  if (user->Status == STAT_NEWUIN) return(5);
}
else {
  if (sel) get(app->LV_OfflineList,MUIA_NList_Active,&entry);
  if (entry >= entries || entry < 0) return(5);
  DoMethod(app->LV_OfflineList,MUIM_NList_GetEntry,entry,&user);
}

sprintf(var,"%s.UIN",newvar);
sprintf(val,"%ld",user->UIN);
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.NICK",newvar);
val2 = (user->Nick?user->Nick:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.FIRST",newvar);
val2 = (user->First?user->First:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));
 
sprintf(var,"%s.LAST",newvar);
val2 = (user->Last?user->Last:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.EMAIL",newvar);
val2 = (user->EMail?user->EMail:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.EMAIL_SECONDARY",newvar);
val2 = (user->EMail_Secondary?user->EMail_Secondary:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.EMAIL_OLD",newvar);
val2 = (user->EMail_Old?user->EMail_Old:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.CITY",newvar);
val2 = (user->City?user->City:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.STATE",newvar);
val2 = (user->State?user->State:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.COUNTRY",newvar);
if (user->Country == 0xffff) strcpy(val,"Unspecified");
else sprintf(val,"%s",FindCountryName(user->Country));
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.PHONE",newvar);
val2 = (user->Phone?user->Phone:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.FAX",newvar);
val2 = (user->FAX?user->FAX:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.CELLULAR",newvar);
val2 = (user->Cellular?user->Cellular:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.HOMEPAGE",newvar);
val2 = (user->HomePage?user->HomePage:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.AGE",newvar);
if (user->Age == 0xffff) strcpy(val,"Unspecified");
else sprintf(val,"%d",user->Age);
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.SEX",newvar);
switch(user->Sex) {
  case 0x00:
    strcpy(val,"Unspecified");
    break;
  case 0x01:
    strcpy(val,"Female");
    break;
  case 0x02:
    strcpy(val,"Male");
    break;
};
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.ABOUT",newvar);
val2 = (user->About?user->About:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.COMMENT",newvar);
val2 = (user->Comment?user->Comment:LINE);
SetRexxVar((struct Message *)rxmsg,var,val2,strlen(val2));

sprintf(var,"%s.IP",newvar);
sprintf(val,"%s",Inet_NtoA(user->IP));
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.PORT",newvar);
sprintf(val,"%d",user->Port);
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.NEWMSGS",newvar);
sprintf(val,"%d",user->NewMsg);
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.STATUS",newvar);
ct = GetStatus(user->Status);
SetRexxVar((struct Message *)rxmsg,var,ct->Status,strlen(ct->Status));

sprintf(var,"%s.LAST_ONLINE",newvar);
sprintf(val,"%s",ctime(&user->LastOnline));
LASTCHAR(val) = '\0';
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.MESSAGE_TO",newvar);
sprintf(val,"%s",ctime(&user->LastMessageTo));
LASTCHAR(val) = '\0';
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

sprintf(var,"%s.MESSAGE_FROM",newvar);
sprintf(val,"%s",ctime(&user->LastMessageFm));
LASTCHAR(val) = '\0';
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

return(0);

}


LONG __asm RxSendMessage(REG(a2) APTR obj, REG(a1) ULONG *array)

{

char *uinstr, *msgstr, *urlstr, *file, *dest, msg[2048];

UBYTE both = MSG_BOTH;

ULONG uin, len;

UWORD type;

struct AsyncFile *load_fh;
struct FileList   File;

uinstr = (char *)*array; array++;
msgstr = (char *)*array; array++;
urlstr = (char *)*array; array++;
file   = (char *)*array; array++;
dest   = (char *)*array;

if (dest) {
  if (!stricmp(dest,"BOTH"))   both = MSG_BOTH;
  if (!stricmp(dest,"LOCAL"))  both = MSG_LOCAL;
  if (!stricmp(dest,"REMOTE")) both = MSG_REMOTE;
}

if (!Online && both != MSG_LOCAL) return(10);

if (!uinstr) return(5);

if (file) {
  strcpy(File.Filename,file);
  len = GetSize(&File);
  if (!(load_fh = OpenAsync(file,MODE_READ,AsyncBuf))) return(15);
  ReadAsync(load_fh,msg,len);
  CloseAsync(load_fh);
  *(msg+len) = '\0';
  msgstr = msg;
//printf("%s\n",msg);
}

if (uinstr) StrToLong(uinstr,(LONG *)&uin);

if (urlstr) {
  sprintf(msg,"%s\xFE%s",msgstr,urlstr);
  type = 0x04;
}
else {
  if (!file) strcpy(msg,msgstr);
  type = 0x01;
}

ARexx = TRUE;

SendAMessage(NULL,uin,msg,type,both,MSG_VIA_BEST);

ARexx = FALSE;

return(0);

}


LONG __asm RxWinControl(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL open, close, state = TRUE, ret = TRUE;

char *win, *uinstr;

ULONG uin = 0, uin2 = 0;

struct Contact *user;

win    = (char *)*array; array++;
open   = *array; array++;
close  = *array; array++;
uinstr = (char *)*array;

if (close) state = FALSE;

if (win) StrToLong(win,(LONG *)&uin);

if (uinstr) StrToLong(uinstr,(LONG *)&uin2);

if (uin) {
  if (user = GetContact(uin)) {
    if (!user->UWin) CreateUserWin(uin);
    if (user->UWin) {
      set(user->UWin->WI_UserWindow,MUIA_Window_Open,state);
      return(0);
    }
    else return(5);
  }
  return(10);
}

if (uin2) {
  if (user = GetContact(uin2)) {
    if (!user->UWin) CreateUserWin(uin2);
    if (user->UWin) {
      if (!stricmp(win,"TRANSFER") && (ret = StartFileXFer(user,FALSE))) set(user->FWin->WI_FileWin,MUIA_Window_Open,state);
//    if (!stricmp(win,"CHAT") && (ret = StartChat(user,FALSE))) set(user->CWin->WI_ChatWin,MUIA_Window_Open,state);
      if (ret) return(0);
      else return(5);
    }
    else return(5);
  }
  return(10);
}

if (!stricmp(win,"FILEDIRECT")) set(app->WI_FileSendOut,MUIA_Window_Open,state);
if (!stricmp(win,"ACTIVITYLOG")) set(app->WI_Activities,MUIA_Window_Open,state);
if (!stricmp(win,"ACTIVESOCKETS")) set(app->WI_Sockets,MUIA_Window_Open,state);
if (!stricmp(win,"MESSAGEHISTORY")) set(app->WI_MessageHist,MUIA_Window_Open,state);
if (!stricmp(win,"STRICQLOG")) set(app->WI_Log,MUIA_Window_Open,state);
if (!stricmp(win,"INCOMINGMESSAGES")) set(app->WI_Message,MUIA_Window_Open,state);
if (!stricmp(win,"SYSTEMMESSAGE")) set(app->WI_URLMessage,MUIA_Window_Open,state);
if (!stricmp(win,"USERINFORMATION")) set(app->WI_Information,MUIA_Window_Open,state);
if (!stricmp(win,"ICQPREFERENCES")) set(app->WI_ICQPrefs,MUIA_Window_Open,state);
if (!stricmp(win,"STRICQ")) set(app->WI_Main,MUIA_Window_Open,state);
if (!stricmp(win,"PAGERMESSAGES")) set(app->WI_WebPager,MUIA_Window_Open,state);

return(0);

}


LONG __asm RxAddFile(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL rem, clr;

char *file;

int i;

ULONG total;

struct FileList Files, *files;

file = (char *)*array; array++;
rem  = *array; array++;
clr  = *array;

if (clr) {
  DoMethod(app->LV_FileList,MUIM_NList_Clear);
  return(0);
}

if (rem) {
  get(app->LV_FileList,MUIA_NList_Entries,&total);
  if (total) {
    for(i = 0; i < total; i++) {
      DoMethod(app->LV_FileList,MUIM_NList_GetEntry,i,&files);
      if (files) {
        if (!stricmp(file,files->Filename)) {
          DoMethod(app->LV_FileList,MUIM_NList_Remove,i);
          SetFileSendStats(NULL);
          return(0);
        }
      }
    }
  }
  return(5);
}

strcpy(Files.Filename,file);

if (!GetSize(&Files)) return(5);

DoMethod(app->LV_FileList,MUIM_NList_InsertSingle,&Files,MUIV_NList_Insert_Sorted);

SetFileSendStats(NULL);

return(0);

}


LONG __asm RxFileDirect(REG(a2) APTR obj, REG(a1) ULONG *array)

{

char *uinstr, *desc, *speedstr;

ULONG uin, total, speed = 100;

struct Contact *user;

uinstr   = (char *)*array; array++;
speedstr = (char *)*array; array++;
desc     = (char *)*array;

if (uinstr) StrToLong(uinstr,(LONG *)&uin);

if (speedstr) {
  StrToLong(speedstr,(LONG *)&speed);
  if (speed > 100) speed = 100;
}

get(app->LV_FileList,MUIA_NList_Entries,&total);

if (!uin || !total) return(5);

if (!desc) desc = "Here are some files.";

set(app->TI_FileReason,MUIA_Textinput_Contents,desc);

set(app->BT_SendFile,MUIA_UserData,uin);

if (user = GetContact(uin)) {
  if (!user->UWin) CreateUserWin(uin);
  if (user->UWin) {
    if (StartFileXFer(user,FALSE)) set(user->FWin->NU_Speed,MUIA_Numeric_Value,speed);
    SendFileSend(app->BT_SendFile);
  }
  else return(10);
}

return(0);

}


LONG __asm RxGetVersion(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL full;

char vers[12], *tmp;

DOUBLE version;

struct RexxMsg *rxmsg = NULL;

full = *array;

get(obj,MUIA_Application_RexxMsg,&rxmsg);

if (full) tmp = version_string;
else {
  version = strtod(version_string+13,NULL);
  sprintf(vers,"%.4f",version);
  tmp = vers;
}

SetRexxVar((struct Message *)rxmsg,ICQRC,tmp,strlen(tmp));

return(0);

}


LONG __asm RxDeleteUIN(REG(a2) APTR obj, REG(a1) ULONG *array)

{

char *uinstr;

ULONG uin;

uinstr = (char *)*array;

if (uinstr) StrToLong(uinstr,(LONG *)&uin);

if (uin) {
  if (!GetContact(uin)) return(10);
  DeleteUIN(uin);
}

return(0);

}


LONG __asm RxGetFiles(REG(a2) APTR obj, REG(a1) ULONG *array)

{

char *newvar, var[50], val[32], *c;

int i;

ULONG total;

struct FileList *file;
struct RexxMsg *rxmsg = NULL;

newvar = (char *)*array;

get(obj,MUIA_Application_RexxMsg,&rxmsg);

if (!newvar) newvar = ICQRC;
else for(c = newvar; *c; c++) *c = ToUpper(*c);

get(app->LV_FileList,MUIA_NList_Entries,&total);

if (total == 0) return(5);

sprintf(var,"%s.0",newvar);
sprintf(val,"%ld",total);
SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));

for(i = 0; i < total; i++) {
  DoMethod(app->LV_FileList,MUIM_NList_GetEntry,i,&file);
  if (file) {
    sprintf(var,"%s.NAME.%d",newvar,i);
    SetRexxVar((struct Message *)rxmsg,var,file->Filename,strlen(file->Filename));
    sprintf(var,"%s.SIZE.%d",newvar,i);
    sprintf(val,"%ld",file->Filesize);
    SetRexxVar((struct Message *)rxmsg,var,val,strlen(val));
  }
}

return(0);

}


LONG __asm RxAcceptChatFile(REG(a2) APTR obj, REG(a1) ULONG *array)

{

BOOL accept = TRUE, acc, dec;

char *uinstr;

ULONG uin = 0;

struct Contact *user;

uinstr = (char *)*array; *array++;
acc = *array; *array++;
dec = *array;

if (dec) accept = FALSE;

if (uinstr) StrToLong(uinstr,(LONG *)&uin);

if (!uin) return(20);

if (!(user = GetContact(uin))) return(5);

if (!user->CFWin) return(10);

if (accept) Accept(user->CFWin->BT_Accept);
else Refuse(user->CFWin->BT_Refuse);

return(0);

}
