#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <limits.h>
#include <iostream.h>
#include <fstream.h>
#include <strings.h>
#include <string.h>
#include <new>
#include <list>

#include "ego.h"
#include "nanny.h"
#include "server.h"
#include "Message.h"

void nanny(Ego *e)
{
   switch(e->getstate())
   {
      case NEWCONNECTION:
      {
         e->write( new Message( Message::Server, "Username") );
         e->setstate(GETUSERNAME);
      }
      break;
      case GETUSERNAME:
      {
         if( e->input() )
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               cout << "Nanny: GETUSERNAME: " << buffer << "\n";
               e->setuser( buffer );
               if( !userok( buffer ) )
               {
                  e->write( new Message( Message::Server, "InvalidUser") );
                  e->setstate(WAITTOCLOSE);
               }
               else if( !knownuser( buffer ) )
               {
                  e->write( new Message( Message::Server, "NewUser") );
                  e->setstate(CHECKUSERNAME);
               }
               else
               {
                  e->write( new Message( Message::Server, "Password") );
                  e->setstate(GETPASSWORD);
               }
            }
            delete msg;
         }
      }
      break;
      case CHECKUSERNAME:
      {
         cerr << "CHECKUSERNAME\n";
         if(e->input())
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               if( strcmp( "YES", buffer ) == 0 )
               {
                  e->write( new Message( Message::Server, "NewPassword") );
                  e->setstate(GETNEWPASSWORD);
               }
               else
               {
                  e->write( new Message( Message::Server, "Username") );
                  e->setstate(GETUSERNAME);
               }
            }
            delete msg;
         }
      }
      break;
      case GETPASSWORD:
      {
         if(e->input())
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               if( e->passmatch( buffer ) )
               {
                  e->write( new Message( Message::Server, "MainMenu") );
                  e->setstate(MAINMENU);
               }
               else
               {
                  e->write( new Message( Message::Server, "Bye") );
                  e->setstate(WAITTOCLOSE);
               }
            }
            delete msg;
         }
      }
      break;
      case GETNEWPASSWORD:
      {
         if(e->input())
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               e->setpass( buffer );
               e->write( new Message( Message::Server, "MainMenu") );
               e->setstate(MAINMENU);
            }
            delete msg;
         }
      }
      break;
      case MAINMENU:
      {
         if(e->input())
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               if( strcmp( "CHAT", buffer ) == 0 )
               {
                  e->write( new Message( Message::Server, "Chat") );
                  e->setstate(CHATMODE);
                  e->listinroom();
                  e->announce( e );
               }
               if( strcmp( "WHITEBOARD", buffer ) == 0 )
               {
                  e->write( new Message( Message::Server, "WhiteBoard") );
                  e->setstate( WHITEBOARD );
               }
               else if( strcmp( "EXIT", buffer ) == 0 )
               {
                  e->write( new Message( Message::Server, "BYE") );
                  e->setstate(WAITTOCLOSE);
                  e->left( e );
               }
            }
            delete msg;
         }
      }
      break;
      case CHATMODE:
      {
         if(e->input())
         {
            Message *msg = e->command();
            char *buffer = NULL;
            if( msg->getType() == Message::Server )
            {
               buffer = msg->getData();
               if( strcmp("EXIT",buffer) == 0 )
               {
                  e->write( new Message( Message::Server, "MAIN") );
                  e->setstate(MAINMENU);
               }
               else if( strcmp("WHO",buffer) == 0 )
               {
                  e->listinroom();
               }
            }
            else if( msg->getType() == Message::Text )
            {
               char start[] = "<";
               char middle[] = "> ";
               int slen = strlen( start );
               int nlen = strlen( e->getuser() );
               int mlen = strlen( middle );
               int dlen = strlen( msg->getData() );
               buffer = new char[ slen + nlen + mlen + dlen + 1 ];
               strcpy( buffer, start );
               strcpy( buffer + slen, e->getuser() );
               strcpy( buffer + slen + nlen, middle );
               strcpy( buffer + slen + nlen + mlen, msg->getData() );
               e->inroom( new Message( Message::Text, buffer) );
               delete buffer;
            }
            delete msg;
         }
      }
      break;
      case WHITEBOARD:
      case WAITTOCLOSE:
      break;
      default:
         cerr << "Nanny: Should NEVER be here!\n";
         break;

   }
}
bool knownuser( char* username )
{
   return false;
}
bool userok( char* username )
{
   return strlen( username ) >= 4;
}

