#include "chat.h"
#include <libraries/dos.h>
#include <intuition/intuitionbase.h>
#include "dh0:code/aelib/ae_pragmas.h"
extern int LocalLog;
extern struct MsgPort *port;
extern struct MsgPort *replymp;
extern struct JHMessage *Jhmsg,*msg;
extern struct Library *AEBase;
struct MsgPort *CreateMasterPrt(UBYTE *name,LONG pri);
char myportnm[10], repportnm[20];
char portnm[NODENUM][20];
int allowed=0;
struct MsgPort *myport, *repport, *otport[NODENUM];
struct MSMes mymes, mesbuf, *otmes;
char mynm[NAMELEN], fname[100];
FILE *str;

char mynm[NAMELEN], otnm[NODENUM][NAMELEN], mainline[100], actst[80],
     namest[50][40];
char dispbuf[100], inkey[100];
int i, j, in, mynd, dnd, col, otno, nodenum, inpt, nmfl, elnfl;
void quitroom(void);
enum Activity act;
enum MainArg mainarg;
#define StartChatReq ChatPermit(1)
#define EndChatReq   ChatPermit(0)
struct SignalSemaphore *sema;
void InitSemi(void);
char SemiName[]= "/X_ChatSemi";
main(int argc,char *argv[])
{
  char t[100];
  Register(argv[1][0]-'0');
  mynd = argv[1][0]-'0'; 
  InitSemi();
  getuserstring(t,BB_TASKPRI);
  Forbid();
  SetTaskPri(FindTask(0),atol(t));
  Permit();
  getuserstring(mynm,DT_NAME);
  getuserstring(mainline,BB_MAINLINE);
  mainarg = parsemain();
  switch( mainarg ) {
   case ON: chaton(); CloseOut();
   case OFF: chatoff(); CloseOut();
   case ERR: chathelp(); CloseOut();
   case NONE: break;
  };

  putuserstring( "\tUsing AEChat Door\n",BB_CALLERSLOG);
  elnfl = 1;
  intro();
  allowed=1;
  dnd = -1;
  nmfl = inpt = col = 0;
  strcpy(inkey," ");
  
  //sprintf(inkey,"[3%dm ", mynd>7 ? 0:mynd+1);
  //inpt=4;
  FOREVER {
    inkey[0]=sigkey(); 
    
    switch( inkey[0] ) {
     case '\0':
  otmes = (struct MSMes *) GetMsg( myport );
    memcpy( &mesbuf, otmes, sizeof(struct MSMes) );
    if(mesbuf.Type==ADD)
    {
       strcpy( otmes->String, mynm );
    }
    ReplyMsg( (struct Message *) otmes );
    switch( mesbuf.Type ) {
     case MES: disp( mesbuf.String, mesbuf.NodeID );
               break;
     case NEWL:dnd = mesbuf.NodeID;
               newln(dnd);
               break;
     case ADD: addnew( mesbuf.String, mesbuf.NodeID );
               dnd = -1;
               break;
     case QUIT:kill( mesbuf.NodeID );
               dnd = -1;
               break;
     default:  sm1( "system error 238"); 
               break;
               /*MSCloseOut();*/
    } break;
     case CTRL('N'): chatwho(1); break;
     case CTRL('F'): dispmenu(); break;
     case CTRL('X'):
      quitroom();
      MSCloseOut();
     case CTRL('P'): page(); break;
     default:
      disp( &inkey, mynd );
      send( MES, ALL );
      
    }
   }

  MSCloseOut(); 

}
void InitSemi(void)
{
  char *Name;
  Forbid();
  if(!(sema=FindSemaphore(SemiName)))
  {
     if(sema=(struct SignalSemaphore *)
        AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC|MEMF_CLEAR))
     {
  Name=AllocMem(strlen(SemiName)+2,MEMF_PUBLIC|MEMF_CLEAR);
  strcpy(Name,SemiName);

       sema->ss_Link.ln_Pri=0;
       sema->ss_Link.ln_Name=Name;
       AddSemaphore(sema);
     }
  }
  Permit();
}    
send( type, who )
{
int i;

   mymes.Type = type;
start:
   switch( type ) {
    case MES:
     strcpy( mymes.String, inkey );
     break;
    case INFO:
     strcpy( mymes.String, mynm );
     break;
    case ADD:
     strcpy( mymes.String, mynm );
     break;
    case NEWL:
    case QUIT:
     break;
   };
   if( who != ALL ) {
    if(!AttemptSemaphore(sema)) return(0);
    PutMsg( otport[who], (struct Message *)&mymes);
    WaitPort(repport);
    if(type==ADD)
    {
      otmes=(struct MSMes *)GetMsg( repport ); 
      strcpy( otnm[who], otmes->String );
    }else GetMsg(repport);
    ReleaseSemaphore(sema);
   }
   else {
    for( i = 0; i < NODENUM; i++ ) {
     if( otport[i] == 0 ) continue;
     if(!AttemptSemaphore(sema)) return(0);
     PutMsg( otport[i], (struct Message *)&mymes);
     WaitPort(repport);GetMsg(repport );

     ReleaseSemaphore(sema);
    };
   };

  return(0);

}
intro()
{
int i;

  op( mynd );
  otno = 0;
  Jhmsg->signal=1L<<myport->mp_SigBit;
  for( i = 0; i < NODENUM; i++ ) {
   otport[i] = 0;
   if( i == mynd ) continue;
   sprintf( portnm[i], "AEChat%d", i );
   otport[i]=FindPort( (UBYTE *) portnm[i] );
   if( otport[i] ) {
    otno++;
    send( ADD, i );
    //WaitPort( myport );
    //otmes = (struct MSMes *) GetMsg( myport );
    //ReplyMsg( (struct Message *) otmes );
   };
  };
  showmessage();
  listother();
  eln();
  sm2( "Press [36m<[0mCtrl-F[36m>[0m To Display Functions" );
  return(0);
}

op(node)
{
 sprintf( myportnm, "AEChat%d", node );
 myport=CreateMasterPrt(myportnm,0L);
 if(myport==0) { sm1("Couldn't create port"); MSCloseOut(); };
 sprintf( repportnm, "AEChatReply%d", node );
 repport=CreatePrt(repportnm,0L);
 if(repport==0) { sm1("Couldn't create reply port"); MSCloseOut(); };

 mymes.Msg.mn_ReplyPort=repport;
 mymes.Msg.mn_Node.ln_Type=NT_MESSAGE;
 mymes.Msg.mn_Length=sizeof(struct MSMes);
 mymes.NodeID = mynd;
 return(0);
}

dispmenu()
{
eln();
sm2( "[36m<[0mCtrl-X[36m>[0m[32m:[0m Exit chat   [36m<[0mCtrl-N[36m>[0m[32m:[0m Who's online   [36m<[0mCtrl-P[36m>[0m[32m:[0m Page Other Nodes   " );
return(0);
}

prd( i )
{
char tm[20];
sprintf( tm, " %d ", i ); sm0( tm );
return(0);
}

addnew( nm, nd )
char *nm;
{
  strcpy( otnm[nd], nm );
  eln();
  sm0( "[33m>>>>>[0m " ); sm0( nm ); sm0( " On Node[32m:[0m [36m([0m" ); prd( nd );
  sm1( "[36m)[0m Has Entered The Chat Room!" );
  cr();
  col = 0;
  sprintf( portnm[nd], "AEChat%d", nd );
  otport[nd]=FindPort( (UBYTE *) portnm[nd] );
  if( otport[nd] == 0 ) { sm1("Couldn't create port"); MSCloseOut(); };
  return(0);
}
        
kill( nd )
{
  eln();
  sm0( "[33m>>>>>[0m " ); sm0( otnm[nd] ); sm0( " On Node[32m:[0m [36m([0m" ); prd( nd );
  sm1( "[36m)[0m Has Left The Chat Room!" );
  cr();
  col = 0;
  otport[nd]=0;
  strcpy( otnm[nd], "[31mKilled[36m![0m" );
  return(0);
}

void quitroom(void)
{
   static int processed=FALSE;
   
   //char temp[100];
if(processed==TRUE) return; else processed=TRUE;
   while( (otmes = (struct MSMes *) GetMsg( myport ))) {
    mesbuf.NodeID = otmes->NodeID;
    switch( otmes->Type ) {
     case QUIT:ReplyMsg( (struct Message *) otmes );
               kill( mesbuf.NodeID );
               break;
     default:  ReplyMsg( (struct Message *) otmes );
               continue;
    };
   };

   send( QUIT, ALL );
        cr();
        sm2( "[36m<[0mExiting From Chat[36m>[0m" );
        Delay( 30 );  
   RemPort( myport );
   RemPort( repport );
   return;
}

newln( n )
{
 if( elnfl == 0 ) cr();
 if( col ) cr();
 if( n == mynd ) { smc0( mynm, 31 ); col = strlen( mynm )+2; }
 else { smc0( otnm[n], 32+n ); col = strlen( otnm[n] )+2; };
 smc0( "> ", 36 );
 dnd = n;
 nmfl = col;
 elnfl = 0;
 return(0);
}

smc0( s, c )
char s[];
{
char tm[100];

 sprintf( tm, "[%dm%s[0m", c, s );
 sm0( tm );
 return(0);
}

nlif()
{
 if( col == 0 ) {
  return(0);
 };
 cr(); col = 0;
 return(0);
}

eln()
{
  nlif(); cr();
  elnfl = 1;
  return(0);
}
showmessage()
{
  cr();
  sm1( "[36m .--------------------------------------------------------------------------.[0m" );
  sm1( "[36m |[0m Ami-Express [33mMulti[32m-[33mNode[0m Interactive Chat Version 1.1 Written by [37m]B]E]E]F[36m  |[0m");
  sm1( "[36m |[0m                       [0m Written for [32mThe Boiler Room[35m.                      [36m|[0m");
  sm1( "[36m |                [44m[33m/X[36m Development Team[0m[37m -[35m The Silent Achievers            [36m    |[0m");
  sm1( "[36m `--------------------------------------------------------------------------'[0m");
  cr();
  return(0);
}

struct MsgPort *CreateMasterPrt(UBYTE *name,LONG pri)
{
  //int sigBit;
  struct MsgPort *mp;
  
  //if((sigBit=AllocSignal(-1L))==-1)
  //  return(NULL);
  mp=(struct MsgPort *)
     AllocMem((ULONG)sizeof(struct MsgPort),(ULONG)MEMF_CLEAR|MEMF_PUBLIC);
  if(!mp)
  {
   // FreeSignal(sigBit);
    return(NULL);
  }
  mp->mp_Node.ln_Name=name;
  mp->mp_Node.ln_Pri=pri;
  mp->mp_Node.ln_Type=NT_MSGPORT;
  mp->mp_Flags=PA_SIGNAL;
  mp->mp_SigBit=getsignal();
  putuserstring("",BB_GETTASK);
  mp->mp_SigTask=(struct Task *)Jhmsg->aeproc;
  if(name)
    AddPort(mp);
  else
    NewList(&(mp->mp_MsgList));
  return(mp);
}
