/*

     .----------------------------------------------------------------.
     | NODE | LOGON | HANDLE                    | ACTiViTY            |
     |======|=======|===========================|=====================|
     |   1  | 17:45 | The Skeleton              | Chat System         |
     |------|-------|---------------------------|---------------------|
     |   2  | --:-- | Awaiting a call           | Idle                |
     |------|-------|---------------------------|---------------------|
     |   3  | --:-- | Awaiting a call           | Idle                |
     `----------------------------------------------------------------'

Press <CTRL-?> to see menu.


<CTRL-S> Send Invite for Chat
<CTRL-W> Who's Online
<CTRL-X> Exit Chat


*/
//**********************
//*****  Includes  *****
//**********************

#include <proto/all.h>
#include <stdio.h>

#include <string.h>
#include <tempest/headers.h>

//********************************
//*****  Structures/Defines  *****
//********************************

struct MyMessage
 {
  struct Message Msg;
  struct User User;
  char text[255],
       text1[255];
  int car,Value,Data;
  long LongValue;
  int  IntValue;
 };

struct User User;
struct MsgPort *MyPort = NULL;
struct MyMessage *msg;
struct node_info nody[15];

#define DROP if(EXIT_FLAG) CloseStuff();

void CloseStuff();
int  DOORIO();
void input(char mstring[],int len);
void WriteFile(char ostring[],char mstring[]);
void Send(int);
void ListNodes(void);
int Loadnody(int);
int CheckKey(void);
void msgs(char *);
void CheckMsg(void);

//******************************
//*****  Global Variables  *****
//******************************

int  NODE,NODES,OTHERNODE=0;
int  EXIT_FLAG, DOOR_DATA, DOOR_CAR, DOOR_VALUE, DOOR_VALUE1 = 0,
     Error,first = 0;
char MyName[255],st[100],DOOR_MSG[255],DOOR_MSG1[255],nodename[255];

//*****************************
//*****  PL (Print Line)  *****
//*****************************

void pl(fmt,a1,a2,a3,a4)
char *fmt;
 {
  char s[255];
  sprintf(s,fmt,a1,a2,a3,a4);
  DOOR_DATA=1; strcpy(DOOR_MSG,s); DOORIO();
 }

//******************
//*****  Main  *****
//******************

void main(int argc,char *argv[])
{
 char string[200],string1[200];
 char string2[200],string3[100]; // Word Rap Only
 int line,stat,key,sending=0,receive=0,back,i;
 register x,y;

 if(!DoorStart(argv[1])) { PutStr("[os2] Tempest Door\n"); exit(0); }

//*************************
//*****  Load Nody's  *****
//*************************

 pl("\r\n[31mPlease Wait.. Loading Info...");

 NODE = atoi(argv[1]);
 stat=Loadnody(NODE);
 if(stat==0)
  {
   pl("NodeInfo File Not Found!\r\n");
   CloseStuff();
  }
 NODES = nody[NODE].SystemDataInfo->NumberOfLines + 1;
 strcpy(nody[NODE].chatmsgbuffer,NULL);
 nody[NODE].chatbuffer[0]=NULL;
 *nody[NODE].chatfromnode=0;
 *nody[NODE].chatroom=0;

 y=0;
 for(x=1;x<NODES+1;x++)
  {
   if(x!=NODE)
    {
     stat=Loadnody(x);
     if(stat==0) setmem(&nody[x],sizeof(struct node_info),NULL);
     if(*nody[x].AN==32) y++;
    }                           // List chat rooms
  }

  // Ask and join which chat room.

 if(y>=2)
  {
   pl("\r\n\r\n[31mSorry, there is already 2 users in live chat system!\r\n\r\n");
   CloseStuff();
  }
 pl("\f[33m[[0mLive Chat Module v0.4[33m]   [36mBy Michael Bockert [33m[[0m01-12-94[33m]\r\n");
 pl("[32m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

//*********************************
//*****  Get Input & Send it  *****
//*********************************

 strcpy(nody[NODE].activity,"Live Chat Module");
 *nody[NODE].AN=32;

 ListNodes();

 sprintf(string,"\r\n\r\n[36m%s [31mhas entered live chat![0m\r\n\r\n",User.Name);
 msgs(string);

 REDO:

 pl("\r\n\r\n[33m<[32mCTRL[0m-[32mS[33m> [36mSend Invite for Chat\r\n[33m<[32mCTRL[0m-[32mW[33m> [36mWho's Online.\r\n[33m<[32mCTRL[0m-[32mX[33m> [36mExit Chat.\r\n\r\n");

 string3[0]=NULL;
 string[0]=NULL;
 x=0;
 line=0;
 CheckMsg();
 while(1)
  {
   REINPUT:

   if(sending==0) CheckMsg();

   //********************************
   //********************************
   //*****  CHECK REMOTE INPUT  *****
   //********************************
   //********************************
   if(nody[NODE].chatbuffer[0]!=NULL)
    {
     if(nody[NODE].chatbuffer[0]==13) pl("\r\n");
     if(receive==0)
      {
       pl("\r\n[31m[[33m%2d[31m] [36m%s[34m>[0m ",*nody[NODE].chatfromnode,nody[*nody[NODE].chatfromnode].UserInfo->Name);
      }
     receive=1;
     sending=0;
     switch(nody[NODE].chatbuffer[0])
      {
       case  8: pl("\b \b"); break;                    // BackSpace
       case 13: break;                                 // Return Key
       default: pl("%c",nody[NODE].chatbuffer[0]);
      }
     *nody[NODE].chatfromnode=0;
     nody[NODE].chatbuffer[0]=NULL;
     goto REINPUT;
    }

   //**************************************
   //**************************************
   //*****  CHECK LOCAL USER'S INPUT  *****
   //**************************************
   //**************************************

   key=CheckKey();
   DROP;
   if(key!=0)
    {
     if(key==13)
      {
       string3[0]=NULL;
       x=0;
       line=0;
       pl("\r\n");
       CheckMsg();
      }
     if((sending==0)&&(key!=8))
      {
       pl("\r\n[31m[[33m%2d[31m] [36m%s[34m>[0m ",NODE,User.Name);
       stat=strlen(User.Name);
       x=stat+7;
       line=x+1;
      }
     receive=0;
     switch(key)
      {
       // BackSpace
       case  8: if((x<1)&&(line==0)) goto REINPUT;
                else if(x<line)      goto REINPUT;
                pl("\b \b");
                x--;
                string3[x]=NULL;
                break;

       // Return Key
       case 13: break;
       case 14: goto REINPUT;

       // CTRL-X or CTRL-C = Quit Program
       case  3:
       case 24: pl("\r\n\r\n");
                sprintf(string,"\r\n\r\n[36m%s [31mhas left live chat![0m\r\n\r\n",User.Name);
                msgs(string);
                strcpy(nody[NODE].activity,"Idle");
                *nody[NODE].AN=30;
                CloseStuff();

       // CTRL-W = List Nodes
       case 23: ListNodes();
                sending=0;
                goto REDO;

       // CTRL-S = Send Invite
       case 19: ListNodes();
                pl("\r\n\r\n[32mInput Node Number to invite[34m: [0m");
                input(string,2);
                DROP;
                y = atoi(string);
                if(nody[y].UserInfo->Name[0]!=NULL)
                 {
                  if((*nody[y].AN!=58)&&(*nody[y].AN!=56)&&(*nody[y].AN!=4))
                   {
                    sprintf(string,"NODE:MsgToNode-%d",y);
                    sprintf(string1,"\r\n[32m%s [32mwould like to chat in InterNode Chat[0m\r\n",User.Name);
                    WriteFile(string,string1);
                   }
                  else pl("\r\n[33mYou can not chat that user at this time!\r\n\r\n");
                  goto REDO;
                 }
                else pl("\r\n[33mNobody on that node!\r\n\r\n");
                sending=0;
                goto REDO;

       default: pl("%c",key);
      }
     Send(key);
     sending=1;
     if(key==13) goto REINPUT;
     else if(key!=8) x++;

     //**********************
     //*****  WORD RAP  *****
     //**********************

     string2[0]=(char)key;
     string2[1]=NULL;
     if(string3[0]==NULL) strcpy(string3,string2);
     else                 strcat(string3,string2);

     if(x>=79)
      {
       strcat(string3,NULL); /// Was the problem!
       back=0;
       stat=strlen(string3);
       for(i=stat;i>0;i--)
        {
         if((stat-i)>15) break;
         if(string3[i-1]==' ')
          {
           back=stat-i;
           break;
          }
        }
       if(back==0)
        {
         Send(13);
         string3[0]=NULL;
         line=0;
         x=0;
         pl("\r\n");
         goto REINPUT;
        }
       string[0]=NULL;

       y=0;
       for(i=(stat-back);i<stat;i++)
        {
         string[y]=string3[i];
         y++;
        }
       string[y]=NULL;
       string3[0]=NULL;

       x=strlen(string);
       for(i=0;i<x;i++)
        {
         pl("\b \b");
         if(i==0) strcpy(string3,"\b \b");
         else     strcat(string3,"\b \b");
        }
       strcat(string3,"\r\n");
       strcat(string3,string);
       msgs(string3);
       string3[0]=NULL;
       line=0;
       pl("\r\n%s",string);
      }
    }
  }
}

//*****************************
//*****  Find Other Node  *****
//*****************************

int FindOtherNode(void)
{
 register int x;
 int stat=0;
 for(x=1;x<NODES+1;x++)
  {
   if((*nody[x].AN==32)&&(x!=NODE))
    {
     OTHERNODE=x;
     stat=1;
    }
  }
 return(stat);
}

//************************************
//*****  Send Text To All Nodes  *****
//************************************

void Send(int key)
{
 register int x;
 int stat=1;
 if((OTHERNODE>0)&&(*nody[OTHERNODE].AN!=32)) stat=FindOtherNode();
 else if(OTHERNODE==0)                        stat=FindOtherNode();
 if(stat==0) return;

 nody[OTHERNODE].chatbuffer[0]=key;
 *nody[OTHERNODE].chatfromnode=NODE;
 for(x=0;x<300;x++)                 // Timer, not endless
  {
   if(*nody[OTHERNODE].chatfromnode==0) return;
  }
}

//****************************************
//*****  Send Messages To All Nodes  *****
//****************************************

void msgs(char message[])
{
 int stat=1;
 if((OTHERNODE>0)&&(*nody[OTHERNODE].AN!=32)) stat=FindOtherNode();
 else if(OTHERNODE==0)                        stat=FindOtherNode();
 if(stat==0) return;

 strcpy(nody[OTHERNODE].chatmsgbuffer,message);
}

//********************************
//********************************
//*****  CHECK FOR MESSAGES  *****
//********************************
//********************************
void CheckMsg(void)
{
 if(nody[NODE].chatmsgbuffer[0]!=NULL)
  {
   pl(nody[NODE].chatmsgbuffer);
   strcpy(nody[NODE].chatmsgbuffer,NULL);
  }
}

//************************
//*****  List Nodes  *****
//************************

void ListNodes(void)
{
 char string[200],string2[20];
 char Handle[40],Activity[30],Time[15];
 register int i;

 pl("\r\n\r\n     [32m.----------------------------------------------------------------.[0m\r\n");
 pl("     [32m| [33mNODE [32m| [33mLoGoN [32m| [33mHANDLE                    [32m| [33mACTiViTY            [32m|\r\n");

//***************************
//*****  Who is Online  *****
//***************************

 i=1;
 do
  {
   strcpy(Handle,nody[i].UserInfo->Name);
   if((*nody[i].hide==1)&&(User.Security!=255)&&(User.Name[0]!=NULL))
    {
     if(nody[i].UserInfo->Slot_Number==1) Handle[0]=NULL;
     else strcpy(Handle,"[ Hiding From Display ]");
    }
   if(Handle[0]!=NULL)
    {
     sprintf(string,"%s",ctime(&nody[i].UserInfo->Time_Last));
     strmid(string,Time,12,5);
     strcpy(Activity,nody[i].activity);
     //**************************
     //*****  Final Output  *****
     //**************************
     pl("     |------|-------|---------------------------|---------------------|\r\n");
//     if(nody[i].NodeDataInfo->LocalMode==0)
     sprintf(string2,"%2d",i);
//     else                                   strcpy(string2," V");
     pl("     |  [36m%2s  [32m| [31m%5s [32m| [0m%-25.25s [32m| [0m%-19s [32m|\r\n",
         string2,Time,Handle,Activity);
    }
   i++;
  }
 while(i<NODES);
 pl("     `----------------------------------------------------------------'[0m");
}

//************************
//*****  Load Nody  ******
//************************

int Loadnody(int node)
{
 char string[50];
 register int y;
 int file;
 sprintf(string,"Node:NodeInfo_%d",node);
 for(y=1;y<3;y++)
  {
   file=Open(string,MODE_OLDFILE);
   if(file!=0)
    {
     Read(file,(char *)&nody[node],sizeof(struct node_info));
     Close(file);
     return(1);
    }
  }
 return(0);
}

//*************************
//*****  Close Stuff  *****
//*************************

void CloseStuff()
{
 DOOR_DATA=99; strcpy(DOOR_MSG,'\0'); DOORIO();
 while(msg=(struct MyMessage *)GetMsg(MyPort)) ReplyMsg((struct Message *)msg);
 if(MyPort) DeletePort(MyPort);
 exit(0); }

 //***********************
 //*****  Check Key  *****
 //***********************

 // This will not wait for a key to be hit, it just simply tells me if
 // there has been one hit, if so the character will be in integer form
 // returned via (x) in this example

 int CheckKey(void)
  { strcpy(DOOR_MSG,'\0'); DOOR_DATA=54; DOOR_VALUE1=0; DOORIO();
    return(DOOR_VALUE1); }

//********************
//*****  DoorIO  *****
//********************

int DOORIO()
{
 struct MsgPort *HisPort;
 struct MyMessage message;
 int UPDATE;
 if(EXIT_FLAG) return 0;
 UPDATE=0;
 HisPort = FindPort(st);
 if(HisPort!=NULL)
  {
   message.Msg.mn_Node.ln_Type = NT_MESSAGE;
   message.Msg.mn_Length = sizeof(message);
   message.Msg.mn_ReplyPort = MyPort;
   if(first)CopyMem(&User,&message.User,sizeof(struct User));
   message.car   = 0;
   message.Data  = DOOR_DATA;
   message.Value = DOOR_VALUE;
   message.IntValue = DOOR_VALUE1;
   strcpy(message.text,DOOR_MSG);
   strcpy(message.text1,DOOR_MSG1);
   PutMsg((struct MsgPort *)HisPort,(struct Message *)&message);
   Wait(1 << MyPort->mp_SigBit);
   GetMsg(MyPort);
   DOOR_DATA  = message.Data;
   DOOR_VALUE = message.Value;
   DOOR_VALUE1 = message.IntValue;
   strcpy(DOOR_MSG,message.text);
   strcpy(DOOR_MSG1,message.text1);
   CopyMem(&message.User,&User,sizeof(struct User));
   first=1;
   UPDATE=0;
   if(message.car) EXIT_FLAG=1;
  }
 return 0;
}

//************************
//*****  Door Start  *****
//************************

DoorStart(char node[])
{
 struct MsgPort *HisPort;
 EXIT_FLAG = 0;
 sprintf(st,"%s:TEMPEST_DOOR",node);
 HisPort = FindPort(st);
 if(HisPort==NULL) return (FALSE);
 sprintf(MyName,"%s:DOOR_PORT",node);
 MyPort = CreatePort(MyName,0L);
 if(MyPort==NULL)
  {
   PutStr("Cant open port");
   return(int)FALSE;
  }
 DOORIO();
 return (int)TRUE;
}

//*******************
//*****  Input  *****
//*******************

void input(char mstring[],int len)
{ DOOR_DATA=40; DOOR_VALUE=len; strcpy(DOOR_MSG,mstring); DOORIO();
 strcpy(mstring,DOOR_MSG); strcpy(DOOR_MSG,'\0'); strcpy(DOOR_MSG1,'\0'); }

//************************
//*****  Write File  *****
//************************

void WriteFile(char ostring[],char mstring[])
{ DOOR_DATA=16; strcpy(DOOR_MSG,ostring); strcpy(DOOR_MSG1,mstring); DOORIO();
 strcpy(DOOR_MSG,'\0'); strcpy(DOOR_MSG1,'\0'); }
