#include "chat.h"

#define SCW 79
#define NODEW 2
#define NAMEW 19
#define LOCW 23
#define ACTW 18
#define STATW (SCW-NODEW-NAMEW-LOCW-ACTW) 

#define DISPSIZE 200

extern enum Activity act;

#define sw1(s) strcpy( actst, s );

extern int mynd, nodenum;
extern char mynm[NAMELEN], fname[100], actst[80], namest[50][40];
extern FILE *str;
extern struct JHMessage *Jhmsg,*msg;
extern struct MsgPort *replymp;

int ret, tok, spact, dispoff=0;
char log[100];
char nodest[80], locst[80], statst[80];

char user[80];

chatwho( outmes )
{
int i;

 putuserstring( "\tUsing NodeInfo\n",BB_CALLERSLOG);

 cr();
 ln1();
 nm();
 ln2();

 for( i = NODENUM-1; i >0; i-- ) if( nodevalid( i ) ) break; 
 nodenum = i + 1;
 for( i = 1; i < nodenum; i++ ) { 
  if( ! nodevalid( i ) ) continue;
  assignsp( i );
  if( i < 10 ) sprintf( nodest, "0%d", i );  
  else sprintf( nodest, "%d", i );
  if( i == mynd ) {
   act = NODEINF;
   strcpy( namest[i], mynm );
   getuserstring( locst, DT_LOCATION );
  } 
  else {
   getnodeact( i );
   if( act == ACERR || act == NOCONN ) { showln( i ); continue; };
   if( act == INACT ) { continue; };
  };
  if( checkstatus( i ) ) strcpy( statst, "Y" );
  else strcpy( statst, "N" );
 
  setact( act );
  showln( i );
 
 };
  
 ln3();
 cr();
 cr();  
 switch( outmes ) {
  case 1: putuserstring( "\tReturned back to AEChat\n",BB_CALLERSLOG); break;
  case 2: putuserstring( "\tNodeInfo Completed\n",BB_CALLERSLOG);
 };
 return(0);
}

end() { exit(0); return(0);}

pad( s, l )
char *s;
{
 memset( &s[strlen(s)], ' ', DISPSIZE - strlen(s) ); 
 s[l+1] = '|';
 s[l+2] = ' ';
 s[l+3] = 0;
 s[SCW-1] = '|';
 s[SCW] = 0;
 return(0);
}

ln1()
{
char tm[DISPSIZE];
 
 memset( tm, '-', SCW );
 tm[0] = '.'; tm[SCW-1] = '.';
 tm[SCW] = 0;
 color( tm, 0, SCW, FRAME ); 
 sm1( tm );
 dispoff = 0;
 return(0);
}

ln2()
{
char tm[DISPSIZE];
 
 memset( tm, '-', SCW );
 tm[0] = '|';
 tm[NODEW+3] = 
 tm[NODEW+NAMEW+6] = 
 tm[NODEW+NAMEW+LOCW+9] = 
 tm[NODEW+NAMEW+LOCW+ACTW+12] = '+';
 tm[SCW-1] = '|'; tm[SCW] = 0;
 color( tm, 0, 1, FRAME );
 color( tm, 1, SCW-2, INFRAME );
 color( tm, SCW-1, 1, FRAME );
 sm1( tm ); 
 dispoff = 0;
 return(0);
}

ln3()
{
char tm[DISPSIZE], ms[100];
int beg = 54; 

 memset( tm, '-', SCW );
 tm[0] = '`'; tm[SCW-1] = '\'';
 strcpy( ms, "InfoNode By ]B]E]E]F" );
 memcpy( &tm[beg], ms, strlen(ms) );
 tm[SCW] = 0;
 color( tm, 0, beg, FRAME );
 color( tm, beg, strlen(ms), YELLOW );
 color( tm, beg+strlen(ms), SCW-beg-strlen(ms), FRAME );
 sm1( tm );
 dispoff=0;
 return(0);
}

nm() {
char tm[DISPSIZE];

 strcpy( tm, "| N#" );
 pad( tm, NODEW+2 );
 strcat( tm, "USER" );
 pad( tm, NODEW+NAMEW+5 );
 strcat( tm, "LOCATION" );
 pad( tm, NODEW+NAMEW+LOCW+8 );
 strcat( tm, "ACTIVITY" );
 pad( tm, NODEW+NAMEW+LOCW+ACTW+11 );
 strcat( tm, "C" );
 padl( tm );
 color( tm, 0, 1, FRAME );
 color( tm, 2, NODEW, YELLOW );
 color( tm, NODEW+3, 1, INFRAME );
 color( tm, NODEW+5, NAMEW, YELLOW );
 color( tm, NODEW+NAMEW+6, 1, INFRAME );
 color( tm, NODEW+NAMEW+8, LOCW, YELLOW );
 color( tm, NODEW+NAMEW+LOCW+9, 1, INFRAME );
 color( tm, NODEW+NAMEW+LOCW+11, ACTW, YELLOW );
 color( tm, SCW-5, 1, INFRAME );
 color( tm, SCW-3, 1, YELLOW );
 color( tm, SCW-1, 1, FRAME );
 sm1( tm ); 
 dispoff = 0;
 return(0);
}

padl(tm)
char *tm;
{
 memset( &tm[strlen(tm)], ' ', SCW - strlen(tm) ); 
 tm[SCW-1] = '|'; tm[SCW] = 0;
 return(0);
}

checkstatus( un )
{
  sprintf( fname, "env:STATUS@%d", un );
  str = fopen( fname, "r" );
  if( str == NULL ) return( 1 );
  fclose( str );
  return( 0 );
}

showln( i )
 {
char disp[DISPSIZE];
 
  strcpy( disp, "| " );
  strcat( disp, nodest );
  pad( disp, NODEW+2 );
  strcat( disp, namest[i] );
  pad( disp, NODEW+NAMEW+5 );
  strcat( disp, locst );
  pad( disp, NODEW+NAMEW+LOCW+8 );
  strcat( disp, actst );
  pad( disp, NODEW+NAMEW+LOCW+ACTW+11 );
  strcat( disp, statst );
  padl( disp );
  color( disp, 0, 1, FRAME );
  color( disp, NODEW+3, 1, INFRAME );
  color( disp, NODEW+NAMEW+6, 1, INFRAME );
  color( disp, NODEW+NAMEW+LOCW+9, 1, INFRAME );
  color( disp, NODEW+NAMEW+LOCW+11, ACTW, CYAN );
  color( disp, SCW-5, 1, INFRAME );
  color( disp, SCW-1, 1, FRAME );
  sm1( disp );
  dispoff = 0;
  ln2();
  return(0);
}

color( s, b, l, c )
char *s;
{
char tmp[DISPSIZE];  

  strcpy( tmp, s );
  sprintf( &s[b+dispoff], "[%dm", c );
  strcat( s, &tmp[b+dispoff] );
  s[b+l+5+dispoff] = 0;
  strcat( s, "[0m" );
  strcat( s, &tmp[b+l+dispoff] );
  dispoff += 9;
  return(0);
}

nodevalid( un )
{
  sprintf( fname, "env:STATS@%d", un );
  str = fopen( fname, "r" );
  if( str == NULL ) return( 0 );
  fclose( str );
  return( 1 );
}

getusernm( i ) 
{
  sprintf( fname, "bbs:node%d.user", i );
  str = fopen( fname,"r" );
  if( str == NULL ) return( ACERR );
  ret = fread( user, 1, 80, str );
  if( ret <= 0 ) return( ACERR );
  strcpy( namest[i], user );
  strcpy( locst, &user[40] );
  fclose( str );
  return( 0 );
}

getnodeact( i )
{
int ret;

   act = parsestats( i );
   if( act == INACT ) return(1);
   if( act == ACERR ) return(1);
   if( act != NOCONN ) ret = getusernm( i );
   if( ret == ACERR ) return(1);
   if( act == NOCONN || act == UNKNOWN || act == SPARE ) act = parselog( i );
   return(0);
}

assignsp( i )
{
   strcpy( namest[i], " " );
   strcpy( locst, " " );
   strcpy( actst, " " );
   strcpy( statst, " " );
   return(0);
}

parsestats( i )
{
char tmp[200];
int stc, ret;

   spact = UNKNOWN;
   sprintf( fname, "env:stats@%d", i );
   str = fopen( fname,"r" );
   if( str == NULL ) return( ACERR ); 
   ret = fread( tmp, 1, 100, str );
   if( ret < 35 ) { fclose( str ); return( ACERR ); };

   tmp[ret] = 0;
   sscanf( &tmp[36], "%d", &stc );
   switch( stc ) {
    case 0: ret = UNKNOWN; break;
    case 1: ret = SPARE; spact = STDOWN; break;
    case 2: ret = SPARE; spact = STUP; break;
    case 3: ret = SPARE; spact = DOOR; break;
    case 8: ret = SPARE; spact = STSCAN; break;
    case 10: ret = SPARE; spact = VIEWTXT; break;
    case 13: ret = SPARE; spact = COMMOP; break;    


    case 4: ret = MESBASE; break; 
    case 5: ret = STATS; break;
    case 6: ret = ACEDIT; break;
    case 7: ret = ZOOM; break;
    case 9: ret = BULL; break;
    case 15: ret = EDIT; break;
    case 14: ret = REMOTE; break;
    case 16: ret = JCONF; break;  
    case 21: 
    case 11: ret = LOGIN; break;
    case 12: ret = LOGOFF; break; 
    case 17: ret = OPCHAT; break;
    case 18: ret = LOSSC; break;     
    case 19: ret = OPCHATREQ; break;

    case 22: ret = NOCONN; break;
    case 23: ret = MAIL; break;
    case 24: ret = INACT; break;
    default: ret = UNKNOWN; break;
   };
   fclose( str );
   return( ret );
}

parse( s )
char *s;
{
char *sc;

 if( ( sc = strstr( log, s ) ) == NULL ) return( 0 );
 tok = sc - log;
 return( 1 );
} 

parselog(i) 
{
int j, k, l, ret;
char buf[200];

   sprintf( fname, "bbs:node%d/callerslog", i );
   str = fopen( fname, "r" );
   if( str == NULL ) return( ACERR );
   /* SEEK_END ?, ok */
   fseek( str, -100L, 2 );
   ret = fread( buf, 100, 1, str );
   if( ret != 1 ) return( ACERR ); 
   buf[99] = 0;
   for( j = 98; j > 0; j-- ) if( buf[j] == '\n' ) break;
   l = 0;
   for( k = j+1; k <= 98; k++ ) {
    if( buf[k] == 9 ) continue;
    log[l++] = buf[k];
   };
   log[l] = 0;
   fclose( str );

   if( act == NOCONN ) {
    if( parse( "Password Failure" ) ) return( HACK );
    return( NOCONN );
   };
   if( act == SPARE ) {
    switch( spact ) {
     case STSCAN: if( parse( "Directory Scan for ") ) return( SCAN );
     case STDOWN: if( parse( "Downloading") ) return ( DOWN );
                  break;
     case STUP:   if( parse( "Uploading") ) return( UP );
                  break;
     case DOOR:   if( parse( "Using AEChat") ) return( CHAT ); 
                  if( parse( "Returned back to AEChat") ) return( CHAT ); 
                  break; 
     case VIEWTXT:if( parse( "SysopView") ) return( SYSVIEW );
     case COMMOP: if (parse( "Account editing" ) ) return ( ACEDIT );    
    };
    return( spact );
   };
  
   if( parse( "Using NodeInfo") ) return( NODEINF ); 
   if( parse( "Conference Joined") ) return( ATCONF ); 
   if( parse( "ailed") ) return( FUCK );
   return( IDLE );       

}

setact( act )
{
int sp, i;
char tmp[100];

   switch( act ) {
    case LOSSC:  sw1( "Lost Carrier" ); break;
    case STUP:   sw1( "Uploading" ); break;
    case STDOWN: sw1( "Downloading" ); break;
    case UP:
     log[33] = 0;
     strcpy( tmp, "U/L: " );
     for( i = 10; log[i]; i++ ) if( log[i] == ' ' ) { log[i] = 0; break; }
     strcat( tmp, &log[10] );
     sw1( tmp ); break;
    case DOWN:
     sw1( "D/L: " );
     sp = tok+12;
     while( log[++sp] != ' ' );
     log[sp] = 0;
     tok = sp-1;
     while( log[tok] != ' ' && log[tok] != '/' && log[tok] != ':' ) tok--;
     strcat( actst, &log[tok+1] );
     break;
    case INACT:  sw1( "Inactive node" ); break;
    case STATS:  sw1( "Examining Status" ); break;
    case NODEINF:sw1( "InfoNode (c) v1.22" ); break;
    case CHAT:   sw1( "Chatting" ); break;
    case DOOR:   sw1( "Door Activity" ); break;
    case BULL:   sw1( "Viewing Bulletins" ); break;
    case ACEDIT: sw1( "Account Edit" ); break;
    case IDLE:   sw1( "Idle" ); break;
    case COMMOP: sw1( "SysOp Functions" ); break;
    case JCONF:  sw1( "Joining Conference" ); break;

    case VIEWTXT:sw1( "Viewing TXT File" ); break;
    case SYSVIEW:sw1( "Sysop Viewing" ); break;
    case HACK:   sw1( "Hacking Account!" ); break;
    case EDIT:   sw1( "Editing Directories" ); break;
    case REMOTE: sw1( "Remote Shell" ); break;
    case STSCAN: sw1( "Scanning Files" ); break;
    case SCAN:   sw1( "Scanning " ); 
                 strcat( actst, &log[19] ); break;
    case FUCK:   sw1( "Failed Upload!" ); break;
    case LOGIN:  sw1( "Logging In" ); break;
    case LOGOFF: sw1( "Logging Off" ); break;
    case ATCONF: sw1( "Joined " ); 
                 while( log[--tok] != '(');              
                 log[tok-1] = 0;
                 strcat( actst, log ); break;
    case OPCHATREQ: sw1( "Paging Operator" ); break;
    case OPCHAT: sw1( "Chatting Operator" ); break;
    case MESBASE:sw1( "Msg Base Activity" ); break;
    case MAIL:   sw1( "Scanning Mail" ); break;
      default:   sw1( "? ? ? ? ?" ); break;
   };
   return(0);
}

page()
{
long t1, t2;
char inp[100], portnm[100], mes[100];
int otnd, ret, tm;
struct MsgPort *otport;
struct JHMessage pagemsg;

  chatwho(1); 
  rep:
  sm0( "[32m-[0m Page Which Node? [36m[[0mNode [33m#[36m][0m Or [36m[[0mQ[36m][0m To Quit[32m:[0m " ); 

  time( &t1 );
  FOREVER {
   if( getkey() ) {
    prompt( "", inp, 2 );
    break;
   }; 
   time( &t2 );
   tm = t2 - t1;
   if( tm > 4 ) {
    sm1( "\n[32m-[0m Timed Out[36m![0m" );
    goto ex;
   };
  };

  if( inp[0] == 'q' || inp[0] == 'Q' ) goto ex;
  if( inp[0] == 0 ) goto rep;

  otnd = -1;
  ret = sscanf( inp, "%d", &otnd );
  if( ret != 1 ) { sm1( "[32m-[0m Invalid Entry[31m![0m" ); goto ex; };
  if( otnd < 1 || otnd >= nodenum ) { sm1( "[32m-[0m Invalid Node[31m![0m" ); goto ex; };
  if( otnd == mynd ) { sm1( "[32m-[0m Page [36m*[0mYourself[36m*[0m For A Monologue??!" ); goto ex; };

  if( checkstatus( otnd ) == 0 ) {
   sprintf( mes, "[32m-[0m Cannot Page Node[32m:[36m%d[0m. User[32m:[0m [36m[[0m%s[36m][0m Is Flagged As Unavailable For Chat!",
    otnd, namest[otnd] ); 
   sm1( mes );
   goto ex;
  };
  getnodeact( otnd );
  switch( act ) {
   case NOCONN: case ACERR: case LOSSC: case HACK:
    sprintf( mes, "[32m-[0m No Connection At Node[32m:[0m [36m[[0m%d[36m][0m", otnd );
    sm1( mes );
    goto ex;
   case CHAT:
    sprintf( mes, "[32m-[0m Node[32m:[0m%d User[32m:[0m [36m[[0m%s[36m][0m Is Already In Chat Mode!", otnd, namest[otnd]  ); 
    sm1( mes );
    goto ex;
   case STUP: case STDOWN: case DOWN: case UP:
   case EDIT: case ACEDIT: case REMOTE:
    setact( act );
    sprintf( mes, "[32m-[0m Cannot Page Right Now, Node[32m:[0m%d User[32m:[0m [36m[[0m%s[36m][0m Is[32m:[0m %s",
     otnd, namest[otnd], actst ); 
    sm1( mes );
    goto ex;
   default: break;
  };
  
  sprintf( portnm, "AEServer.%d", otnd );
  otport = FindPort( (UBYTE *)portnm );
  if( otport == 0 ) { sm1( "[32m-[0m Node Unavailable[31m![0m" ); goto ex; };
  pagemsg.Msg.mn_Node.ln_Type=NT_MESSAGE;
  pagemsg.Msg.mn_Length=sizeof(struct JHMessage);
  pagemsg.Msg.mn_ReplyPort=0;
  pagemsg.Data = 0;
  pagemsg.Command = 3;
  sprintf(pagemsg.String,
   "\a\n\r\n\r[31mChat Request![0m From Node[32m:[36m( [33m%d[36m )[0m User[32m: [36m[[0m%s[36m][0m\n\r\n\r", mynd, mynm );
  PutMsg(otport, (struct Message *)&pagemsg);
  sprintf(pagemsg.String, "Press [36m[[33mReturn[36m][0m To Resume BBS Operations. Use [36m[[0mCHAT[36m][0m To Chat With [32m%s[0m\n\r\n\r", mynm );
  PutMsg(otport, (struct Message *)&pagemsg);
  sprintf( mes, "[32m-[0m Chat Request Sent To Node[32m:[36m( [33m%d[36m )[0m User[32m: [36m[[0m%s[36m][0m", otnd, namest[otnd] ); 
  sm1( mes );
  cr();
  return(0);

  ex:
  sm1( "[32m-[0m Operation Aborted[31m![0m\n");
  return(1);

}

LastCommand()
{
 return(0);
}

sm(mstring,nl)
char *mstring;
{
int i;
  Jhmsg->Data = 0;
  Jhmsg->Command = 3;
  strcpy(Jhmsg->String,mstring);
  PutToPort((struct Message *)Jhmsg);
  (void)WaitPort(replymp);
  (void)GetMsg(replymp);
  for( i = 0; i < nl && i < 30; i++ ) cr();
  return(0);
}

cr() { sm0( "\r\n" ); return(0);}

bs() { sm0( "\b \b" );  return(0);}

bsn(n)
{
int i;
 for( i = 0; i < n; i++ ) bs();
 return(0);
}

