/////////////////////////////////////////////////////////////////////////////
//
//   TLCPAL.CPP
//
//   Copyright (c) 1997 Galacticomm, Inc.         All Rights Reserved
//
//   Teleconference Pals Implementation file
//
//                                              - Phil Henning 8/18/97
//
/////////////////////////////////////////////////////////////////////////////

#include "gcomm.h"
#include "majorbbs.h"
#include "tlcapi.hpp"
#include "gcspsrv.h"
#include "tlccs.h"

#define FILREV "$Revision: 23 $"
MARKSOURCE(tlcpal)

DFAFILE* dfaPal;
CHAR* pglo;
INT pmax;
CHAR* pkey;
USHORT* ppref;
LPPALMEM pmem;
VOID* pmemreg;

GBOOL usepalt;

INT palglo(VOID);

VOID palList();

SHORT palAdd(const CHAR* user);
GBOOL palRemove(const CHAR* user);
GBOOL palCheck(const CHAR* user);
GBOOL palVerify(const CHAR* user);
GBOOL palIsOnline(const CHAR* user);
VOID  palUpdateCS(INT unum);

GBOOL (* palvrfyhook)(const CHAR* user);
GBOOL (* palisonhook)(const CHAR* user);

GBOOL palVerifyDft(const CHAR* user);
GBOOL palIsOnlineDft(const CHAR* user);
CHAR* tvar_palglo(VOID);

VOID
initpal()
{
     dfaPal=dfaOpen(PALFILE,sizeof(PALDSK),NULL);
     pmax=numopt(PALMAX,1,50);
     pkey=stgopt(PALKEY);
     palvrfyhook=palVerifyDft;
     palisonhook=palIsOnlineDft;
     usepalt=ynopt(USEPALT);

     if (usepalt) {
          pglo=stgopt(PALGLO);
          globalcmd(palglo);
          pmemreg=alcblok(nterms,(sizeof(PALMEM)*pmax));
          for (int i = 0 ; i < nterms ; i++) {
               LPPALMEM ptr;
               ptr=GETPALPTR(i);
               memset(ptr,0,sizeof(PALMEM)*pmax);
          }
          ppref=static_cast<USHORT*>(alczer(nterms*sizeof(USHORT)));
     }
     register_textvar("TELE_PALGLO",tvar_palglo);
}

VOID
palSave(
INT unum,
GBOOL updateself)
{
     LPPALMEM ptr;
     PALDSK pdsk;

     ptr=GETPALPTR(unum);
     dfaSetBlk(dfaPal);
     memset(&pdsk,0,sizeof(PALDSK));
     stzcpy(pdsk.pszUserid,uacoff(unum)->userid,UIDSIZ);
     for (int i=0 ; i < pmax ; i++) {
          if (ptr->pszPal[0] != '\0') {
               stzcpy(pdsk.pszPal,ptr->pszPal,TLCUIDSIZ);
               if (!dfaQueryEQ(&pdsk,0)) {
                    dfaInsert(&pdsk);
               }
          }
          ptr++;
     }
     stzcpy(pdsk.pszPal,pdsk.pszUserid,TLCUIDSIZ);
     stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
     if (updateself) {
          pdsk.ldate=today();
          pdsk.ltime=now();
          pdsk.lelapsed=(usroff(unum)->minut4)/4;
          if (dfaAcqEQ(NULL,&pdsk,0)) {
               dfaUpdate(&pdsk);
          }
          else {
               pdsk.flags=PAL_FLAG_LON|PAL_FLAG_LOF|PAL_FLAG_LMSG;
               dfaInsert(&pdsk);
          }
     }
     dfaRstBlk();
}

VOID
palClear(
INT unum)
{
     LPPALMEM ptr;

     ptr=GETPALPTR(unum);
     memset(ptr,0,sizeof(PALMEM)*pmax);
}

VOID
palLoad(
INT unum)
{
     LPPALMEM ptr;
     PALDSK pdsk;
     int i;

     ptr=GETPALPTR(unum);
     memset(ptr,0,sizeof(PALMEM)*pmax);
     memset(&pdsk,0,sizeof(PALDSK));
     stzcpy(pdsk.pszUserid,uacoff(unum)->userid,UIDSIZ);

     i=0;
     dfaSetBlk(dfaPal);
     if (dfaAcqGT(&pdsk,&pdsk,0) && sameas(pdsk.pszUserid,uacoff(unum)->userid)) {
          do {
               strcpy(ptr->pszPal,pdsk.pszPal);
               if (!dfaAcqNX(&pdsk)) {
                    break;
               }
               ptr++;
          } while (++i < pmax);
     }
     stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
     stzcpy(pdsk.pszPal,uacoff(unum)->userid,TLCUIDSIZ);
     if (!dfaAcqEQ(&pdsk,&pdsk,0)) {
          palSave(unum);
          dfaAcqEQ(&pdsk,&pdsk,0);
     }
     ppref[unum]=pdsk.flags;
     dfaRstBlk();
}

VOID
palWasUpdated(
INT unum)
{
     if (usroff(unum)->flags&ISGCSU) {
          palUpdateCS(unum);
     }
     else if (usepalt) {
          palLoad(unum);
     }
}

VOID
palUpdateCS(
INT unum)
{
     PALDSK pdsk;
     memset(cssndbuf,0,CSSNDBUFSIZ);
     memset(&pdsk,0,sizeof(PALDSK));
     stzcpy(pdsk.pszUserid,usaptr->userid,UIDSIZ);
     dfaSetBlk(dfaPal);
     strcat(cssndbuf,spr("%d\t",pmax));
     if (dfaAcqGT(&pdsk,&pdsk,0)
      && sameas(pdsk.pszUserid,curUser->GetName())) {
          do {
               strcat(cssndbuf,spr("%s\t",pdsk.pszPal));
          } while (dfaAcqNX(&pdsk));
     }
     if (qroom(unum,NORMAL)) {
          cnvd2s(tlcdpks[DPK_PALUPDATE],namtmp);
          senddpk(unum,TLCAPID,NORMAL,namtmp,STGLEN,cssndbuf,NULL);
     }
}

SHORT
palAdd(
const CHAR* user)
{
     LPPALMEM ptr;
     GBOOL added=FALSE;

     if (palCheck(user)) {
          return(PAL_ALREADY);
     }
     ptr=GETPALPTR(usrnum);
     for (int i=0 ; i < pmax ; i++) {
          if (ptr->pszPal[0] == '\0') {
               stzcpy(ptr->pszPal,user,TLCUIDSIZ);
               added=TRUE;
               break;
          }
          ptr++;
     }
     if (added) {
          palSave(usrnum,FALSE);
          return(PAL_ADDED);
     }
     return(PAL_TOOMANY);
}

GBOOL
palCheck(
const CHAR* user)
{
     LPPALMEM ptr;

     ptr=GETPALPTR(usrnum);
     for (int i=0 ; i < pmax ; i++) {
          if (sameas(ptr->pszPal,user)) {
               return(TRUE);
          }
          ptr++;
     }
     return(FALSE);
}

GBOOL
palRemove(
const CHAR* user)
{
     LPPALMEM ptr;

     ptr=GETPALPTR(usrnum);
     for (int i=0 ; i < pmax ; i++) {
          if (sameas(ptr->pszPal,user)) {
               memset(ptr->pszPal,0,TLCUIDSIZ);
               palSave(usrnum,FALSE);
               return(TRUE);
          }
          ptr++;
     }
     return(FALSE);
}

GBOOL
palVerify(
const CHAR* user)
{
     return(palvrfyhook(user));
}

GBOOL
palVerifyDft(
const CHAR* user)
{
     dfaSetBlk(accbb);
     if (dfaQueryEQ(user,0)) {
          return(TRUE);
     }
     return(FALSE);
}

VOID
palStatus(
const CHAR* user)
{
     LPPALMEM ptr;
     GBOOL found=FALSE;

     ptr=GETPALPTR(usrnum);
     if (user != NULL) {
          for (int i=0 ; i < pmax ; i++) {
               if (sameas(ptr->pszPal,user)) {
                    PALDSK pdsk;
                    dfaSetBlk(dfaPal);
                    stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
                    stzcpy(pdsk.pszPal,ptr->pszPal,TLCUIDSIZ);
                    prfmsg(PALSTHD2);
                    if (palIsOnline(pdsk.pszPal)) {
                         prfmsg(PALSTAO2,pdsk.pszPal);
                    }
                    else if (dfaAcqEQ(&pdsk,&pdsk,0)) {
                         prfmsg(PALSTAT2,pdsk.pszPal,
                          ncdatel(pdsk.ldate),nctime(pdsk.ltime),
                          pdsk.lelapsed);
                    }
                    else {
                         prfmsg(PALSTAN2,user);
                    }
                    prfmsg(PALSTFT2);
                    dfaRstBlk();
                    found = TRUE;
                    break;

               }
               ptr++;
          }
          if (!found) {
               prfmsg(PALNOFN2,user);
          }
     }
     else {
          prfmsg(PALSTHD2);
          dfaSetBlk(dfaPal);
          for (int i=0 ; i < pmax ; i++) {
               if (ptr->pszPal[0] != '\0') {
                    PALDSK pdsk;
                    stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
                    stzcpy(pdsk.pszPal,ptr->pszPal,TLCUIDSIZ);

                    if (palIsOnline(pdsk.pszPal)) {
                         prfmsg(PALSTAO2,pdsk.pszPal);
                    }
                    else if (dfaAcqEQ(&pdsk,&pdsk,0)) {
                         prfmsg(PALSTAT2,pdsk.pszPal,
                          ncdatel(pdsk.ldate),nctime(pdsk.ltime),
                          pdsk.lelapsed);
                    }
                    else {
                         prfmsg(PALSTAO2,ptr->pszPal);
                    }
                    found=TRUE;
               }
               ptr++;
          }
          dfaRstBlk();
          if (!found) {
               prfmsg(PALNONE2);
          }
          prfmsg(PALSTFT2);
     }
}

GBOOL
palIsOnline(
const CHAR* user)
{
     return(palisonhook(user));
}

GBOOL
palIsOnlineDft(
const CHAR* user)
{
     if (onsys(user)) {
          return(TRUE);
     }
     return(FALSE);
}

VOID
palList(VOID)
{
     LPPALMEM ptr;

     ptr=GETPALPTR(usrnum);
     prfmsg(PALLIHD2);
     for (int i=0 ; i < pmax ; i++) {
          if (ptr->pszPal[0] != '\0') {
               prfmsg(PALLIDA2,ptr->pszPal);
          }
          ptr++;
     }
     prfmsg(PALLIFT2);
}

VOID
palNotify(
const CHAR* user,
SHORT type)
{
     LPPALMEM ptr;

     setmbk(msgTlc);
     prfmlt((type == PAL_LOGON ? PALISON2 : PALISOF2),user);
     for (int i=0 ; i < nterms ; i++) {
          if (usroff(i)->usrcls == ACTUSR
           && !(usroff(i)->flags&ISGCSU)) {
               if (type == PAL_LOGON && !(ppref[i]&PAL_FLAG_LON)) {
                    continue;
               }
               else if (type == PAL_LOGOFF && !(ppref[i]&PAL_FLAG_LOF)) {
                    continue;
               }
               else {
                    ptr=GETPALPTR(i);
                    onsysn(uacoff(i)->userid,1);
                    for (int j=0 ; j < pmax ; j++) {
                         if (sameas(ptr->pszPal,user)) {
                              injoth();
                              break;
                         }
                         ptr++;
                    }
               }
          }
     }
     rstmbk();
     clrmlt();
}

VOID
palToggleNotify(
SHORT type)
{
     PALDSK pdsk;

     setmbk(msgTlc);
     memset(&pdsk,0,sizeof(PALDSK));
     stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
     stzcpy(pdsk.pszPal,usaptr->userid,TLCUIDSIZ);
     dfaSetBlk(dfaPal);
     if (!dfaAcqEQ(&pdsk,&pdsk,0)) {
          palSave(usrnum,TRUE);
          dfaAcqEQ(&pdsk,&pdsk,0);
     }

     if (type == PAL_LOGON) {
          if (pdsk.flags&PAL_FLAG_LON) {
               pdsk.flags&=~PAL_FLAG_LON;
          }
          else {
               pdsk.flags|=PAL_FLAG_LON;
          }
     }
     else {
          if (pdsk.flags&PAL_FLAG_LOF) {
               pdsk.flags&=~PAL_FLAG_LOF;
          }
          else {
               pdsk.flags|=PAL_FLAG_LOF;
          }
     }
     dfaUpdate(&pdsk);
     dfaRstBlk();
}

VOID
palToggleLogon()
{
     PALDSK pdsk;

     setmbk(msgTlc);
     memset(&pdsk,0,sizeof(PALDSK));
     stzcpy(pdsk.pszUserid,PALTRAK,UIDSIZ);
     stzcpy(pdsk.pszPal,usaptr->userid,TLCUIDSIZ);
     dfaSetBlk(dfaPal);
     if (!dfaAcqEQ(&pdsk,&pdsk,0)) {
          palSave(usrnum,TRUE);
          dfaAcqEQ(&pdsk,&pdsk,0);
     }
     if (pdsk.flags&PAL_FLAG_LMSG) {
          pdsk.flags&=~PAL_FLAG_LMSG;
     }
     else {
          pdsk.flags|=PAL_FLAG_LMSG;
     }
     dfaUpdate(&pdsk);
     dfaRstBlk();
}


INT
palglo(VOID)
{
     INT retval=1;

     if (!sameas(pglo,margv[0]) || !haskey(pkey)) {
          return(0);
     }
     setmbk(msgTlc);
     if (margc == 1) {
          palStatus();
     }
     else if (sameas("help",margv[1]) || sameas("?",margv[1])) {
          prfmsg(PALHLP3,pmax);
     }
     else if (sameas("add",margv[1])) {
          rstrin();
          if (palVerify(margv[2])) {
               SHORT result;
               result=palAdd(margv[2]);
               switch (result) {
               case PAL_ALREADY:
                    prfmsg(PALALRD2,margv[2],pglo,margv[2]);
                    break;
               case PAL_ADDED:
                    prfmsg(PALADD2,margv[2]);
                    break;
               case PAL_TOOMANY:
                    prfmsg(PALTOOM2);
                    break;
               }
          }
          else {
               prfmsg(PALNOSC2,margv[2]);
          }
     }
     else if (sameas("remove",margv[1]) || sameas("rem",margv[1])) {
          rstrin();
          if (palCheck(margv[2])) {
               palRemove(margv[2]);
               prfmsg(PALRMD2,margv[2]);
          }
          else {
               prfmsg(PALNOFN2,margv[2]);
          }
     }
     else if (sameas("list",margv[1])) {
          palList();
     }
     else if ((sameas("status",margv[1]) || sameas("stat",margv[1]))
      && margc == 2) {
          // status of all users on list
          palStatus();
     }
     else if (sameas("status",margv[1]) || sameas("stat",margv[1])) {
          rstrin();
          // status of user starting at margv[2]
          if (palCheck(margv[2])) {
               palStatus(margv[2]);
          }
          else {
               prfmsg(PALNOFN2,margv[2]);
          }
     }
     else if (sameas("lon",margv[1])) {
          palToggleNotify(PAL_LOGON);
     }
     else if (sameas("lof",margv[1])) {
          palToggleNotify(PAL_LOGOFF);
     }
     else if (sameas("lmsg",margv[1])) {
          palToggleLogon();
     }
     else {
          retval=0;
     }
     if (retval) {
          outprf(usrnum);
     }
     rstmbk();
     return(retval);
}

CHAR*
tvar_palglo(VOID)
{
     return(pglo);
}
