/////////////////////////////////////////////////////////////////////////////
//
//   TLCWORCH.CPP
//
//   Copyright (c) 1997  Galacticomm, Inc.        All Rights Reserved
//
//   Worldlink Teleconference Channel
//   Implementation
//                                               - Phil Henning 7/15/97
//
/////////////////////////////////////////////////////////////////////////////

#include "gcomm.h"
#include "majorbbs.h"
#include "tlcwor.h"
#pragma option -w-par
#include "tlcwfda.h"
#include "wortlc.h"

#define FILREV "$Revision: 53 $"

MARKSOURCE(tlcworch);

CHFUNCPTRS worChannel={
     NULL,
     NULL,
     NULL,
     WorChAddUser,
     WorChRemoveUser,
     WorChPreWelcome,
     NULL,
     WorCanAccess
};

static VOID
addFromContext(                    // add @FU macro to beginning
CHAR* fmt);                        // string to add to


SHORT
WorChAddUser(
const CHAR* channel,
LPUSRSTRUCT pUser,
GBOOL bIsFirstEnter)
{
     JINFSTR jinfo;
     LPCHANINFO pInfo;
     (VOID)bIsFirstEnter;

     if (tlcChannelGetUser(channel,pUser->m_pszName) != NULL) {
          return(CHAN_JOIN_ALREADY);
     }
     memset(&jinfo,0,sizeof(JINFSTR));
     jinfo.unum=worUseridToNumber(pUser->m_pszName);
     jinfo.tlcunum=tlcUserFindID(pUser->m_pszName);
     pInfo=tlcChannelGetInfo(channel);
     ASSERT(pInfo != NULL);
     jinfo.chn=static_cast<LPWORCHANCUSTOM>(pInfo->m_pCustom)->num;
     if (!(pUser->m_fFlags&USR_INVISB)) {
          worSendFDA(WORAPID,WORCMD_USER_JOIN,sizeof(JINFSTR),&jinfo,jinfoFDA);
          jinfo.chn=pUser->m_fFlags&USR_UNLIST;
          worSendFDA(WORAPID,WORCMD_USER_UNLISTED,sizeof(JINFSTR),&jinfo,jinfoFDA);
     }
     return(CHAN_JOIN_OK);
}

SHORT
WorChRemoveUser(
const CHAR* channel,
LPUSRSTRUCT pUser,
SHORT fExitType)
{
     JINFSTR jinfo;
     LPCHANINFO pInfo;
     (VOID)fExitType;

     memset(&jinfo,0,sizeof(JINFSTR));
     jinfo.unum=worUseridToNumber(pUser->m_pszName);
     pInfo=tlcChannelGetInfo(channel);
     ASSERT(pInfo != NULL);
     jinfo.chn=(static_cast<LPWORCHANCUSTOM>(pInfo->m_pCustom))->num;
     if (!(pUser->m_fFlags&USR_INVISB)) {
          worSendFDA(WORAPID,WORCMD_USER_UNJOIN,sizeof(JINFSTR),&jinfo,jinfoFDA);
     }
     return(CHAN_UNJOIN_OK);
}

VOID
WorChPreWelcome(
LPUSRSTRUCT pUser)
{
     tlcUserSendText(pUser->m_pszName,SYSUID,NULL,pUser->m_pszChannel,RECV_TYPE_WELCOME,WLCHN,0,0,0);
}


VOID
WorChAddNetworkUser(
const CHAR* channel,
const CHAR* userid)
{
     USRSTRUCT User;
     ULONG unum;
     USHORT bnum;
     LPJINFSTR jinfo;
     LPCHANINFO pInfo;
     VOID* ptr;
     WORUSER wu;

     unum=worAliasToNumber(userid);
     if (tlcUserInChannel(userid,channel) || unum == WLUSER_NOT_FOUND) {
          return;
     }
     bnum=static_cast<USHORT>(unum/WLUSERS_PER_BOARD);
     ptr=pSmbUsers->GetEqual(&unum,0);

     if (ptr != NULL) {
          jinfo=static_cast<LPJINFSTR>(ptr);
          pInfo=tlcChannelGetInfo(channel);

          ASSERT(pInfo != NULL);
          jinfo->chn=static_cast<LPWORCHANCUSTOM>(pInfo->m_pCustom)->num;

          memset(&User,0,sizeof(USRSTRUCT));
          strcpy(User.m_pszName,userid);
          User.m_iUsrnum=-2;
          User.m_ulTlcUnum=unum;
          User.m_uiTlcBoardNum=bnum;
          User.m_fFlags|=USR_INCHAN;
          if (worGetUserInfoByAlias(&wu,userid)) {
               User.m_chSex = (wu.Flags&WLUSER_MALE ? 'M' : 'F');
               User.m_iAge = (wu.Age);
          }
          tlcUserCreate(&User,iWorTrans,channel);
          tlcPublicSendAllChannels(User.m_pszName,
                                   NULL,
                                   NULL,
                                   RECV_TYPE_USERENTER,
                                   0);
     }
}

VOID
WorChRemoveNetworkUser(
const CHAR* channel,
const CHAR* userid)
{
     LPJINFSTR jinfo;
     LPCHANINFO pInfo;
     LPUSRSTRUCT pUser;
     ULONG unum;
     VOID* ptr;

     pUser=tlcChannelGetUser(channel,userid);
     if (pUser == NULL) {
          // just return if the user isn't here
          return;
     }
     unum=pUser->m_ulTlcUnum;
     ptr=pSmbUsers->GetEqual(&unum,0);
     tlcChannelSetContext(channel);
     if (ptr != NULL) {
          SHORT num;
          jinfo=(LPJINFSTR)ptr;
          pInfo=tlcChannelGetInfo(channel);
          ASSERT(pInfo != NULL);
          num=static_cast<LPWORCHANCUSTOM>(pInfo->m_pCustom)->num;
          if (jinfo->chn == num) {
               jinfo->chn=-1;
          }
     }
     if (pUser->m_fFlags&USR_CHATTING) {
          LPUSRSTRUCT pOthUser;
          pOthUser=tlcUserGetInfo(tlcUserGetChatUser(pUser->m_pszName));
          if (pOthUser != NULL && (pOthUser->m_fFlags&USR_CHATTING)) {
               if (sameas(tlcUserGetChatUser(pOthUser->m_pszName)
                         ,pUser->m_pszName)) {
                    tlcUserSetChatUser(pOthUser->m_pszName, NULL);
                    ExitChat(TRUE,pOthUser->m_pszName,FALSE);
               }
          }
     }
     tlcTransRemoveUser(iWorTrans,pUser);
     tlcPublicSendAllChannels(userid,NULL,NULL,RECV_TYPE_USEREXIT,0);
     tlcUserRemove(userid,channel);
}

VOID
WorChWLRecv(
const CHAR* channel,
const CHAR* pszUseridFrom,
const CHAR* pszUseridTo,
const CHAR* pMsg,
SHORT fType,
SHORT iMsgNum,
const CHAR* ptr1,
const CHAR* ptr2,
const CHAR* ptr3)
{
     INT numtrans=tlcTransGetNumber();
     const CHAR* key=NULL;

     if (fType == RECV_TYPE_DIRECTED) {
          ULONG num;
          num=(ULONG)atol(ptr1);
          ptr1=worNumberToUserid(num);
          if (worWorldUser(ptr1) != 0) {
               ptr1=worUseridToAlias(ptr1);
          }
          if (*ptr1 == '\0') {
               return;
          }
     }
     else if (fType == RECV_TYPE_ENTCHAT) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(pszUseridFrom);
          if (pUser != NULL) {
               pUser->m_fFlags|=USR_CHATTING;
               pUser->m_fFlags&=~USR_INCHAN;
          }
     }
     else if (fType == RECV_TYPE_RETCHAT) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(pszUseridFrom);
          if (pUser != NULL) {
               tlcUserSetChatUser(pUser->m_pszName,NULL);
               pUser->m_fFlags&=~USR_CHATTING;
               pUser->m_fFlags|=USR_INCHAN;
          }
     }
     else if (fType == RECV_TYPE_ENTEREDEDIT) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(pszUseridFrom);
          if (pUser != NULL) {
               pUser->m_fFlags|=USR_INEDIT;
               pUser->m_fFlags&=~USR_INCHAN;
          }
     }
     else if (fType == RECV_TYPE_RETEDIT) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(pszUseridFrom);
          if (pUser != NULL) {
               pUser->m_fFlags&=~USR_INEDIT;
               pUser->m_fFlags|=USR_INCHAN;
          }
     }
     if (*pszUseridFrom != '\0') {
          for (int count=0 ; count < numtrans ; count++) {
               if (count != iWorTrans) {
                    tlcTransSendAllKey(count
                                   ,pszUseridFrom,
                                   pszUseridTo,
                                   pMsg,
                                   fType,
                                   channel,
                                   iMsgNum,
                                   ptr1,
                                   ptr2,
                                   ptr3,
                                   key);
               }
          }
     }
}

VOID
WorChWLAction(
LPACTIONINF pAct,
const CHAR* channel)
{
     WORUSER wu;
     CHAR tostg[TLCUIDSIZ];
     CHAR fromstg[TLCUIDSIZ];
     const CHAR* action;
     GBOOL all=FALSE;
     LPUSRSTRUCT pFromUser;

     if (!worGetUserInfoByNumber(&wu,pAct->from)) {
          *fromstg='\0';
     }
     else if (wu.BoardNumber == 0) {
          stlcpy(fromstg,wu.Userid,TLCUIDSIZ);
     }
     else {
          stlcpy(fromstg,worNumberToAlias(pAct->from),TLCUIDSIZ);
     }
     if (pAct->to == ACTTOALL) {
          all=TRUE;
     }
     else {
          if (!worGetUserInfoByNumber(&wu,pAct->to)) {
               *tostg='\0';
          }
          else if (wu.BoardNumber == 0) {
               stlcpy(tostg,wu.Userid,TLCUIDSIZ);
          }
          else {
               stlcpy(tostg,worNumberToAlias(pAct->to),TLCUIDSIZ);
               if (sameas(tostg,"")) {
                    return;
               }
          }
     }
#ifdef DEBUG2
     shocst("WORCHWLACTION FROM","%s",fromstg);
     shocst("WORCHWLACTION TO","%s",tostg);
#endif

     pFromUser=tlcUserGetInfo(fromstg);
     if (pFromUser == NULL || pFromUser->m_fFlags&USR_SQUELCH) {
          return;
     }
     // copy action
     ACTION tmpa;

     memset(&tmpa,0,sizeof(ACTION));
     strcpy(tmpa.name,pAct->name);
     tmpa.isyell=pAct->isyell;

     if (!actHasFromUser(pAct->fmt)) {
          addFromContext(pAct->fmt);
     }
     if (!pAct->iscomplex) {
          strcpy(tmpa.simple,pAct->fmt);
          if ((action=fmtsimpall(&tmpa,fromstg)) != NULL) {
               for (int i=0; i < tlcTransGetNumber() ; i++) {
                    if (i != iWorTrans) {
                         tlcTransSendAllKey(i,fromstg,tostg,action,
                          RECV_TYPE_ACTION,channel,ACTMSG_OUT,NULL,NULL,NULL,
                          worRatingKey(pAct->rate));
                    }
               }
          }
     }
     else if (pAct->isyell) {
          strcpy(tmpa.complx,pAct->fmt);
          if ((action=fmtcomplxall(&tmpa,fromstg,tostg,pAct->extra)) != NULL) {
               for (int j=0; j < tlcTransGetNumber() ; j++) {
                    if (j != iWorTrans) {
                         tlcTransSendAllKey(j,fromstg,tostg,action,
                          RECV_TYPE_ACTION,channel,ACTMSG_OUT,NULL,NULL,NULL,
                          worRatingKey(pAct->rate));
                    }
               }
          }
     }
     else {
          LPUSRSTRUCT pUser;
          strcpy(tmpa.complx,pAct->fmt);
          if (all) {
               action=fmtcomplxall(&tmpa,fromstg,"all",pAct->extra);
          }
          else {
               action=fmtcomplxall(&tmpa,fromstg,tostg,pAct->extra);
          }
          if (action != NULL) {
               pUser=tlcChannelGetFirstUser(channel);
               while (pUser != NULL) {
                    CHAR saved[TLCUIDSIZ];
                    stlcpy(saved,pUser->m_pszName,TLCUIDSIZ);
                    if (sameas(pUser->m_pszName,tostg)
                     || sameas(pUser->m_pszName,fromstg)) {
                         pUser=tlcChannelGetUserGT(channel,saved);
                         continue;
                    }
                    if (tlcUserCheckAccess(pUser->m_pszName
                                          ,worRatingKey(pAct->rate))) {
                         tlcUserSendText(pUser->m_pszName,fromstg,NULL,action
                                        ,RECV_TYPE_ACTION,ACTMSG_OUT
                                        ,NULL,NULL,NULL);
                    }
                    pUser=tlcChannelGetUserGT(channel,saved);
               }
               clrmlt();
          }
    }
}


SHORT
WorChWLActionUser(
LPACTIONINF pAct,
const CHAR* user,
const CHAR* channel,
GBOOL secret)
{
     WORUSER wu;

     CHAR fromstg[TLCUIDSIZ];
     CHAR tostg[TLCUIDSIZ];
     const CHAR* action;

     if (!worGetUserInfoByNumber(&wu,pAct->to) || wu.BoardNumber != 0) {
          return(ACTION_NOUSR);
     }
     else {
          stlcpy(tostg,wu.Userid,TLCUIDSIZ);
     }
     stlcpy(fromstg,worNumberToAlias(pAct->from),TLCUIDSIZ);

#ifdef DEBUG2
     shocst("WORCHWLACTIONUS FROM","%s",fromstg);
     shocst("WORCHWLACTIONUS TO","%s",tostg);
     shocst("WORCHWLACTIONUS BNUM","%ld",wu.BoardNumber);
#endif

    // copy action
     ACTION tmpa;

     memset(&tmpa,0,sizeof(ACTION));
     strcpy(tmpa.name,pAct->name);
     tmpa.isyell=pAct->isyell;

     if (!actHasFromUser(pAct->fmt)) {
          addFromContext(pAct->fmt);
     }

     LPUSRSTRUCT pUser=tlcUserGetInfo(tostg);
     if (!sameas(channel,pUser->m_pszChannel)) {
          return(ACTION_NOUSR);
     }
     if (pUser != NULL) {
          if (tlcUserCheckForget(pUser->m_pszName,fromstg)) {
               return(ACTION_FORGET);
          }
          if (tlcUserCheckIgnore(pUser->m_pszName,fromstg)) {
               return(ACTION_IGNORE);
          }
          if (tlcUserCheckAccess(pUser->m_pszName,worRatingKey(pAct->rate))) {
               if (!(pUser->m_fFlags&USR_SQUELCH)) {
                    if (pAct->iscomplex && !(pAct->isyell)) {
                         strcpy(tmpa.complx,pAct->fmt);
                         if ((action=fmtcomplxto(&tmpa,fromstg,tostg)) != NULL) {
                              tlcUserSendText(pUser->m_pszName,fromstg,NULL,action
                                    ,RECV_TYPE_ACTION
                                    ,secret ? ACTMSG_OUT_SECRET : ACTMSG_OUT
                                    ,NULL,NULL,NULL);
                         }
                    }
                    if (!secret) {
                         if (channel != NULL) {
                              WorChWLAction(pAct,channel);
                         }
                    }
               }
               return(0);
          }
          return(ACTION_NOACS);
     }
     return(ACTION_NOUSR);
}

GBOOL                              //   TRUE/FALSE
WorCanAccess(                      // can user access channel
const CHAR* channel,               //   channel name
LPUSRSTRUCT pUser,                 //   user structure
INT access)                        //   access being requested
{
     ASSERT(pUser != NULL);
     ASSERT(channel != NULL);

     LPCHANINFO pInfo=tlcChannelGetInfo(channel);
     ASSERT(pInfo != NULL);
     if (pInfo == NULL) {
          return(FALSE);
     }
     ASSERT(pInfo->m_type&CHAN_TYPE_WL_PUBLIC);
     LPWORCHANCUSTOM pCu=(LPWORCHANCUSTOM)(pInfo->m_pCustom);
     ASSERT(pCu != NULL);
     if (pCu == NULL) {
          shocst("WORLDLINK TELECONFERENCE","No Data for %s",pInfo->m_strName);
          return(FALSE);
     }
     switch (access) {
     case CHAN_AXS_SEE:
     case CHAN_AXS_JOIN:
     case CHAN_AXS_SPEAK:
          return(tlcUserCheckAccess(pUser->m_pszName,worRatingKeyBynum(pCu->rating)));
     default:
          return(FALSE);
     }
}

static VOID
addFromContext(                    // add @FU macro to beginning
CHAR* fmt)                         // string to add to
{
     CHAR oldfmt[RESSIZ];

     setmbk(wortlcmsg);
     stlcpy(oldfmt,fmt,RESSIZ);

     stlcpy(fmt,rawmsg(FUPMT),RESSIZ);
     stlcat(fmt,oldfmt,RESSIZ);
     rstmbk();
}
