/***************************************************************************
 *                                                                         *
 *   REGTVB.CPP                                                            *
 *                                                                         *
 *   Copyright (c) 1998       Galacticomm, Inc.    All Rights Reserved.    *
 *                                                                         *
 *   Active HTML Registry Text Variables                                   *
 *   Implementation                                                        *
 *                                                                         *
 *                                                - Phil Henning 8/20/98   *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "regsyn.h"
#include "regtvb.h"
#include "registry.h"
#include "galregis.h"
#include "galregah.h"
#include <strstrea.h>


#define FILREV "$Revision: 5 $"
#define REGNOLIST 9                     // number of NOLIST variables
#define REGNOTARG 9                     // number of REGTARGET variables

enum tvbtype {TVB_BASIC,TVB_HTML,TVB_ENC,TVB_LINKED};

basicTvb regIsAuth("REG_ISAUTH");
basicTvb regHasCompleted("REG_HASCOMPLETED");
htmlEncodedTvb regHasCompletedText("REG_HASCOMPLETED_TEXT");

basicTvb regErrCode("RERR_CODE");
htmlEncodedTvb regErrMessage("RERR_MESSAGE");

htmlEncodedTvb regUserid("REG_USERID");
urlEncodedTvb regUseridURL("REG_USERID_URL");

basicTvb** regQuestionN=NULL;           // REG_QUESTION_n
basicTvb** regAnswerN=NULL;             // REG_ANSWER_n
basicTvb** regMaxAnsN=NULL;             // REG_MAXANS_n

basicTvb regQuestionNumber("REG_QUESTION_NUMBER");

basicTvb regLargestAns("REG_LARGESTANS");

basicTvb regCanDelete("REG_CANDELETE");
htmlEncodedTvb regCanDeleteText("REG_CANDELETE_TEXT");
basicTvb regMaxAns("REG_MAXANS");

basicTvb regListCount("RLST_COUNT");
basicTvb regListOrder("RLST_ORDER");
basicTvb regListMoreHigh("RLST_MORE_HIGH");
basicTvb regListMoreLow("RLST_MORE_LOW");
urlEncodedTvb regListUserHigh("RLST_USER_HIGH");
urlEncodedTvb regListUserLow("RLST_USER_LOW");
basicTvb** regNoList=NULL;              // REG_NOLIST_n
basicTvb** regTarget=NULL;              // REG_TARGET_n

htmlEncodedTvb regNew("REG_NEW");
htmlEncodedTvb regNewText("REG_NEW_TEXT");

linkedHtmlEncodedTvb* regQuestion=NULL; // REG_QUESTION
linkedHtmlEncodedTvb* regAnswer=NULL;   // REG_ANSWER
linkedHtmlEncodedTvb* regSummaryQ=NULL; // REG_SUMMARYQ
linkedHtmlEncodedTvb* regSummaryA=NULL; // REG_SUMMARYA

INT g_numQuestions=0;                   // num of question vars
CHAR* g_pszNoList[REGNOLIST];           // array of REG_NOLIST mcv options
CHAR* g_pszTarget[REGNOTARG];           // array of REG_TARGET mcv options
CHAR* g_pszErrMessage[REGNOERR];        // array of error message strings
CHAR* g_pszAnchor=NULL;                 // anchor format string

CHAR* g_pszComplt=NULL;                 // REG_HASCOMPLETED_TEXT
CHAR* g_pszNComplt=NULL;                // REG_HASCOMPLETED_TEXT
CHAR* g_pszCanDel=NULL;                 // REG_CANDEL_TEXT
CHAR* g_pszNCanDel=NULL;                // REG_CANDEL_TEXT
CHAR* g_pszNewEn=NULL;                  // REG_NEW_TEXT
CHAR* g_pszNNewEn=NULL;                 // REG_NEW_TEXT

static VOID
registerRange(                          // register a range of Tvbs
basicTvb ** tvbPtr,                     //   pointer to tvbs
enum tvbtype ttype,                     //   tvb type to create
CHAR const * pszBody,                   //   body to set equal to
INT num,                                //   set from 0-num
CHAR const * anchor=NULL);              //   anchor to use for linking

static VOID
setTvbArray(                            // set tvbs to set or cleared state
basicTvb** tvbPtr,                      //   pointer to tvbs
CHAR** repStrings,                      //   strings to set with
INT numElems,                           //   number of tvbs/strings
bool bClear);                           //   clear them?

MARKSOURCE(regtvb);

VOID
setupUserContext(                       // setup question/summary answers
const struct regrec& rec)               //   based on this registry record
{
     regUserid=rec.userid;
     regUseridURL=rec.userid;
     for (int i=0 ; i < numfds ; ++i) {
          *(regAnswerN[i])=(&rec.profil[0])+reginf[i].ansidx;
     }
     *regSummaryA=rec.sumlin;
}

VOID
linkAnswers(                            // toggle linking on answer tvbs
bool link)                              //   link on/off
{
     for (int i=0; i < numfds ; i++) {
          dynamic_cast<linkedHtmlEncodedTvb*>(regAnswerN[i])->toggleLink(link);
     }
     regSummaryA->toggleLink(link);
     regAnswer->toggleLink(link);
}

VOID
clearAllTVars()                         // clear all registry tvbs
{
     ASSERT(g_pszNComplt != NULL);
     ASSERT(g_pszNCanDel != NULL);
     ASSERT(g_pszNewEn != NULL);
     dnfClearTemplateTvb();
     regIsAuth=0;
     regHasCompleted=0;
     regHasCompletedText=g_pszNComplt;
     regErrCode=0;
     regErrMessage="";
     regUserid="";
     regUseridURL="";
     *regQuestion="";
     *regAnswer="";
     regMaxAns=0;
     regQuestionNumber=0;
     *regSummaryA="";
     regCanDelete=0;
     regCanDeleteText=g_pszNCanDel;
     regListCount=0;
     regListOrder="";
     regListMoreHigh=0;
     regListMoreLow=0;
     regListUserHigh="";
     regListUserLow="";
     regNew=1;
     regNewText=g_pszNewEn;
     setNoList(false);
     setTarget(false);
}

VOID
setNewTvb(                              // set REG_NEW and REG_NEW_TEXT
bool isnew)                             //   is new?
{
     if (isnew) {
          regNew=1;
          regNewText=g_pszNewEn;
     }
     else {
          regNew=0;
          regNewText=g_pszNNewEn;
     }
}

VOID
setNoList(                              // set REG_NOLIST tvbs
bool bIsList)                           //   was there a list?
{
     ASSERT(regNoList != NULL);
     ASSERT(g_pszNoList != NULL);
     setTvbArray(regNoList,g_pszNoList,REGNOLIST,!bIsList);
}

VOID
setTarget(                              // set REG_TARGET tvbs
bool bTarget)                           //   set them?
{
     ASSERT(regTarget != NULL);
     ASSERT(g_pszTarget != NULL);
     setTvbArray(regTarget,g_pszTarget,REGNOTARG,!bTarget);
}

VOID
setAllQuestions()                       // setup all the REG_QUESTION_n vars
{
     INT largestSize=0;

     ASSERT(regQuestionN != NULL);
     ASSERT(regMaxAnsN != NULL);
     ASSERT(numfds == g_numQuestions);
     setmbk(regmb);
     for (int i=0 ; i < numfds ; i++) {
          *(regQuestionN[i])=stpans(getmsg(FLDLBL1+(4*i)));
          largestSize=max(reginf[i].anssiz,largestSize);
          *(regMaxAnsN[i])=reginf[i].anssiz;
     }
     regLargestAns=largestSize;
     *regSummaryQ=stpans(stgopt(SUMLBL));
     rstmbk();
}

VOID
setCurrentQuestion(                     // setup REG_QUESTION
INT idx)                                //   to this question index
{
     ASSERT(idx < g_numQuestions);
     *regQuestion=*(regQuestionN[idx]);
     regQuestionNumber=idx+1;
     regMaxAns=*(regMaxAnsN[idx]);
}

VOID
setCurrentAnswer(                       // setup REG_ANSWER
INT idx)                                //  to this answer index
{
     ASSERT(idx < g_numQuestions);
     *regAnswer=*(regAnswerN[idx]);
}

VOID
clearAllAnswers()                       // clear all REG_ANSWER_n vars
{
     ASSERT(regAnswerN != NULL && *regAnswerN != NULL);
     for (int i=0 ; i < g_numQuestions ; i++) {
          *(regAnswerN[i])="";
     }
}

VOID
initQuestionTxv(                        // init Q/A text variables
INT num)
{
     static bool init=false;
     if (init) {
          return;
     }
     regQuestionN=new basicTvb* [num];
     regAnswerN=new basicTvb* [num];
     regMaxAnsN=new basicTvb* [num];
     regNoList=new basicTvb* [REGNOLIST];
     regTarget=new basicTvb* [REGNOTARG];
     registerRange(regQuestionN,TVB_LINKED,"REG_QUESTION_",num,g_pszAnchor);
     registerRange(regAnswerN,TVB_LINKED,"REG_ANSWER_",num,g_pszAnchor);
     registerRange(regMaxAnsN,TVB_BASIC,"REG_MAXANS_",num);
     registerRange(regNoList,TVB_BASIC,"REG_NOLIST_",REGNOLIST);
     registerRange(regTarget,TVB_BASIC,"REG_TARGET_",REGNOTARG);
     ASSERT(g_pszAnchor != NULL);
     regQuestion=new linkedHtmlEncodedTvb("REG_QUESTION",g_pszAnchor);
     regAnswer=new linkedHtmlEncodedTvb("REG_ANSWER",g_pszAnchor);
     regSummaryQ=new linkedHtmlEncodedTvb("REG_SUMMARYQ",g_pszAnchor);
     regSummaryA=new linkedHtmlEncodedTvb("REG_SUMMARYA",g_pszAnchor);
     g_numQuestions=num;
     init=true;
}

VOID
finishQuestionTxv()                     // shutdown Q/A vars
{
     if (regQuestionN != NULL) {
          for (int i=0 ; i < g_numQuestions ; i++) {
               if (regQuestionN[i] != NULL) {
                    delete regQuestionN[i];
               }
          }
          delete [] regQuestionN;
          regQuestionN=NULL;
     }
     if (regAnswerN != NULL) {
          for (int i=0 ; i < g_numQuestions ; i++) {
               if (regAnswerN[i] != NULL) {
                    delete regAnswerN[i];
               }
          }
          delete [] regAnswerN;
          regAnswerN=NULL;
     }
     if (regMaxAnsN != NULL) {
          for (int i=0 ; i < g_numQuestions ; i++) {
               if (regMaxAnsN[i] != NULL) {
                    delete regMaxAnsN[i];
               }
          }
          delete [] regMaxAnsN;
          regMaxAnsN=NULL;
     }
     for (int i=0 ; i < REGNOLIST ; i++) {
          if (regNoList[i] != NULL) {
               delete regNoList[i];
               regNoList[i]=NULL;
          }
     }
     for (int i=0 ; i < REGNOTARG ; i++) {
          if (regTarget[i] != NULL) {
               delete regTarget[i];
               regTarget[i]=NULL;
          }
     }
     if (regQuestion != NULL) {
          delete regQuestion;
          regQuestion=NULL;
     }
     if (regAnswer != NULL) {
          delete regAnswer;
          regAnswer=NULL;
     }
     if (regSummaryQ != NULL) {
          delete regSummaryQ;
          regSummaryQ=NULL;
     }
     if (regSummaryA != NULL) {
          delete regSummaryA;
          regSummaryA=NULL;
     }
     g_numQuestions=0;
}

VOID
initMcvText()                           // initialize MCV options
{
     static bool init=false;
     ASSERT(regahmb != NULL);
     if (init) {
          return;
     }
     setmbk(regahmb);
     g_pszComplt=stpans(stgopt(COMPLT));
     g_pszNComplt=stpans(stgopt(NCOMPLT));
     g_pszCanDel=stpans(stgopt(CANDEL));
     g_pszNCanDel=stpans(stgopt(NCANDEL));
     g_pszNewEn=stpans(stgopt(NEWEN));
     g_pszNNewEn=stpans(stgopt(NONEWEN));
     // read NOLISTn options from mcv file.
     for (int i=0, j=NOLIST1 ; i < REGNOLIST ; i++,j++) {
          g_pszNoList[i]=stpans(stgopt(j));
     }
     for (int i=0, j=RTARGET1 ; i < REGNOTARG ; i++,j++) {
          g_pszTarget[i]=stpans(stgopt(j));
     }
     for (int i=0, j=RERROR1 ; i < REGNOERR ; i++, j++) {
          g_pszErrMessage[i]=stpans(stgopt(j));
     }
     init=true;
     rstmbk();
}

VOID
finishMcvText()                         // free up stored MCV options
{

     if (g_pszComplt != NULL) {
          free(g_pszComplt);
          g_pszComplt=NULL;
     }
     if (g_pszNComplt != NULL) {
          free(g_pszNComplt);
          g_pszNComplt=NULL;
     }
     if (g_pszCanDel != NULL) {
          free(g_pszCanDel);
          g_pszCanDel=NULL;
     }
     if (g_pszNCanDel != NULL) {
          free(g_pszNCanDel);
          g_pszNCanDel=NULL;
     }
     if (g_pszNewEn != NULL) {
          free(g_pszNewEn);
          g_pszNewEn=NULL;
     }
     if (g_pszNNewEn != NULL) {
          free(g_pszNNewEn);
          g_pszNNewEn=NULL;
     }
     for (int i=0 ; i < REGNOLIST ; i++) {
          if (g_pszNoList[i] != NULL) {
               free(g_pszNoList[i]);
               g_pszNoList[i]=NULL;
          }
     }
     for (int i=0 ; i < REGNOTARG ; i++) {
          if (g_pszTarget[i] != NULL) {
               free(g_pszTarget[i]);
               g_pszTarget[i]=NULL;
          }
     }
     for (int i=0 ; i < REGNOTARG ; i++) {
          if (g_pszErrMessage[i] != NULL) {
               free(g_pszErrMessage[i]);
               g_pszErrMessage[i]=NULL;
          }
     }
}

VOID
setHasCompletedTvb(                     // set REG_HASCOMPLETED tvars
CHAR const * userid)                    //   userid to check
{
     ASSERT(userid != NULL);
     if (userid == NULL) {
          return;
     }
     dfaSetBlk(regbb);
     if (dfaQueryEQ(userid,0)) {
          regHasCompleted=1;
          regHasCompletedText=g_pszComplt;
     }
     else {
          regHasCompleted=0;
          regHasCompletedText=g_pszNComplt;
     }
     dfaRstBlk();
}

VOID
setCanDelete(                           // set REG_CANDELETE tvar
bool candelete)                         //   does user have delete access?
{
     if (candelete) {
          regCanDelete=1;
          regCanDeleteText=g_pszCanDel;
     }
     else {
          regCanDelete=0;
          regCanDeleteText=g_pszNCanDel;
     }

}

static VOID
registerRange(                          // register a range of Tvbs
basicTvb ** tvbPtr,                     //   pointer to tvbs
enum tvbtype ttype,                     //   tvb type to create
CHAR const * pszBody,                   //   body to set equal to
INT num,                                //   set from 0-num
CHAR const * anchor)                    //   anchor to use for linking
{
     ASSERT(tvbPtr != NULL);
     ASSERT(pszBody != NULL);
     ASSERT(*pszBody != '\0');

     for (int i=0 ; i < num ; i++) {
          ostrstream ost;
          ost << pszBody << i+1 << ends;
          switch (ttype) {
          case TVB_BASIC:
               tvbPtr[i]=new basicTvb(ost.str());
               break;
          case TVB_HTML:
               tvbPtr[i]=new htmlEncodedTvb(ost.str());
               break;
          case TVB_ENC:
               tvbPtr[i]=new urlEncodedTvb(ost.str());
               break;
          case TVB_LINKED:
               if (anchor != NULL ) {
                    tvbPtr[i]=new linkedHtmlEncodedTvb(ost.str(),anchor);
               }
               else {
                    tvbPtr[i]=new htmlEncodedTvb(ost.str());
               }
               break;
          default:
               ASSERTM(FALSE,"Bad TVB type");
          }
          ost.rdbuf()->freeze(0);
     }
}

static VOID
setTvbArray(                            // set tvbs to set or cleared state
basicTvb** tvbPtr,                      //   pointer to tvbs
CHAR** repStrings,                      //   strings to set with
INT numElems,                           //   number of tvbs/strings
bool bClear)                            //   clear them?
{
     ASSERT(tvbPtr != NULL);
     if (tvbPtr == NULL || *tvbPtr == NULL) {
          return;
     }
     if (bClear || repStrings == NULL) {
          for (int i=0 ; i < numElems ; i++) {
               *(tvbPtr[i])="";
          }
          return;
     }
     for (int i=0 ; i < numElems ; i++) {
          *(tvbPtr[i])=repStrings[i];
     }
}

VOID
setErrorVars(                           // set error code vars
errorcodes code)                        //   to this error
{
     regErrCode=(INT)code;
     ASSERT(code >= 0 && code <= REGNOERR);
     if (code > 0 && code <= REGNOERR) {
          regErrMessage=g_pszErrMessage[code-1];
     }
}
