#include <strings.h>
#include  "xbugchess.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>

#define PORTNUM 2152
#define BOARD1 0
#define BOARD2 2
#define PACKSIZE 10

#define TRUE 1 
int USING_BSD = 0 ;
int dsock[4],main_sock;
fd_set fdset,rfdset;
char names[4][50];

void end_game();

struct player_struct {
  int color ;
  int sock;
  int pmesg;
  char *eptr;
  char *pptr;
  char buffer[1024];
} player[4];

struct player_struct *white[2], *black[2];
int PNUM = 2;
main(argc, argv)
int argc;
char *argv[];
{
  int counter;

  signal(SIGINT, end_game);
 
  if ((main_sock = establish(PORTNUM)) < 0) {  /* plug in the phone */
    perror("establish");
    exit(1);
  }
  if(!strcmp(argv[1], "fuzzy-brownies")) {
    PNUM = 4; 
    USING_BSD = TRUE;
    strcpy(argv[1], "xbugchess");
  }

  if(!strcmp(argv[1], "xbugchess")) {
    PNUM = 4;
    system("zwrite -i bugchess -m bugchess daemon started on `/bin/hostname`");
  }
  printf("It's %s time!!! \n" , argv[1]);

  initplayers();
  puts("Waiting for connections...");
  for(counter=0;counter< PNUM;) {    /* loop for phone calls */
    if ((dsock[counter]=get_connection(main_sock)) < 0) { /* get connection */
      if (errno == EINTR)             /* EINTR might happen on accept(), */
	continue;                     /* tryagain */
      perror("accept");               /* bad */
      exit(1);
    }
    getname(counter);
    counter++;
  }
  close(main_sock);
  setup_fd();
  shownames(argv);
  if (PNUM = 4 ) brief_players();
  switch(fork()) {
  case -1:
    perror("fork");
    end_game();
  case 0:
    break;
  default:
    puts("Daemon running. . . ");
    exit(0);
  }

  relay_messages();

}

    
setup_fd() 
{
  int counter = 0;

  FD_ZERO(&fdset);
  while (counter < PNUM) {
    FD_SET(dsock[counter],&fdset);
    counter++;
  }
}

relay_messages()
{
  int which, n_byte;
  int counter=0;
  int i=0;
  char buffer[1024];
  while(1) {
    rfdset=fdset;
    if((which=get_a_socket())== -2) { perror("socket"); }

    if(counter++ > 1000) {
      fprintf(stderr, "error count over 10000, exiting . . .");
      end_game();
    }

    n_byte=read_data(dsock[which],buffer,PACKSIZE);

#ifdef DEBUG 
    printf("Bytes read = %d \n",n_byte);
#endif

    for (i = 0 ; i < PNUM ; i++) {
#ifdef DEBUG
      printf("Sending to %d : %d %d %d %d \n",i, buffer[0],buffer[1],
	     buffer[2], buffer[3]);
#endif 
      write_data(dsock[i],buffer,PACKSIZE);
    }
  }
  
  
}

getname(reported)
int reported;
{
  int talkto;
  char messag;
  FD_ZERO(&rfdset);

    read_data(dsock[reported],&messag,1);
    player[reported].pmesg++;

#ifdef DEBUG
    printf("From Player %d, a name of length %d\n",reported,(int)messag);
#endif 

    read_data(dsock[reported],player[reported].pptr,(int)messag);
    printf("Welcome Player %d: %s \n",reported+1, player[reported].pptr);
    player[reported].eptr=player[reported].pptr+(int)messag;

}



SetPredeterminedPlayers(arg) 
char *arg[];
{
  int i;
  int counter, input ,whitein;
  int  temp;


  for(i = 0 ; i < 4; i ++ ) {
    puts(arg[i+2 ]);
  }
  puts("Them are all the players");

  for(counter = 0; counter < PNUM/ 2 ; counter++) {
    for (i = 0 ; i < 4 ; i++) {
      printf("Comparing %s and %s \n",arg[counter*2 +2] , player[i].pptr);
      if( !strncasecmp(arg[counter*2 + 2] , player[i].pptr,strlen(arg[counter*2 +2 ]))) {
	printf(" white will be %s \n", player[i].pptr);
	whitein = i;
	player[whitein].color = WHITE | (counter * 2);
	white[counter] = &player[whitein];
	break;
      }
    }
    if (i == 4) {puts(" NOT FOUND!!! "); exit(1);}

    for (i = 0 ; i < 4 ; i++) {
      printf("Comparing %s and %s \n",arg[counter*2 +3] , player[i].pptr);
      if( !strncasecmp(arg[counter*2 + 3] , player[i].pptr,strlen(arg[counter*2+3]))) {
	printf(" black will be %s \n", player[i].pptr);
	input = i;
	player[input].color = BLACK | (counter * 2);
	black[counter] = &player[input];
	break;
      }
    }
    if (i == 4) {puts(" NOT FOUND!!! "); exit(1);}
    
    player[input].color=BLACK | (counter*2) ;
    black[counter]=&player[input];

    temp=strlen(names[input]);
    names[input][temp+1]=(char)player[whitein].color;
    write_data(dsock[whitein],names[input],50);

    temp=strlen(names[whitein]);
    names[whitein][temp+1]=(char)player[input].color;
    write_data(dsock[input],names[whitein],50);
    
  }
}

shownames(arg)
char *arg[];
{
  int counter,i,temp;
  int input;
  int whitein;

  puts("People Reported:\n");

  for (counter=0;counter<PNUM;counter++) {
    printf("%d ) %s\n",counter+1,player[counter].pptr);
    strcpy(names[counter],player[counter].buffer);
  }

  for (counter=0;counter<PNUM/2 ;counter++) {
    if(USING_BSD) {
      for (i = 0 ; i < 4 ; i++) {
	printf("Comparing %s and %s \n",arg[counter*2 +2] , player[i].pptr);
	if( !strncasecmp(arg[counter*2 + 2] , player[i].pptr,strlen(arg[counter*2 +2 ]))) {
	  printf(" white will be %s \n", player[i].pptr);
	  whitein = i;
	  break;
	}
      }
    } else  {
      do { 
	printf("Who will be WHITE? \n");
	scanf("%d",&whitein); 
	whitein--;
	fflush(stdin);
	fflush(stdout);
      } while ((whitein >=  PNUM) && (whitein < 0));
    }
    puts(names[whitein]);
    if(player[whitein].color!= -1) {
      puts("Already chosen rechoose");
      player[whitein].color = -1;
      counter--;
      continue;
    }
    player[whitein].color = WHITE | (counter*2);
    white[counter] = &player[whitein];
	
    if(USING_BSD) {
      for (i = 0 ; i < 4 ; i++) {
	printf("Comparing %s and %s \n",arg[counter*2 +3] , player[i].pptr);
	if( !strncasecmp(arg[counter*2 + 3] , player[i].pptr,strlen(arg[counter*2+3]))) {
	  printf(" black will be %s \n", player[i].pptr);
	  input = i;
	  break;
	}
      }
    } else { 
      do { 
	printf("Who will be BLACK?  \n");
	scanf("%d", &input); 
	input--;
	fflush(stdin);
	fflush(stdout);
      } while ((input >=  PNUM) && (input < 0));
    }

    puts(names[input]);
    if(player[input].color!= -1) {
      puts("Already chosen rechoose");
      player[whitein].color = -1;
      player[input].color = -1;
      counter--;
      continue;
    }
    player[input].color=BLACK | (counter*2) ;
    black[counter]=&player[input];

    temp=strlen(names[input]);
    names[input][temp+1]=(char)player[whitein].color;
    write_data(dsock[whitein],names[input],50);

    temp=strlen(names[whitein]);
    names[whitein][temp+1]=(char)player[input].color;
    write_data(dsock[input],names[whitein],50);
    
  }

  puts("ALRIGHT!!! And away we go... ");
}

brief_players()
{
  int counter, i;
  for(counter = 0; counter < PNUM; counter++) {
    for(i = 0; i < PNUM; i++) {
      /* SUPER KLUDGE!!! */
      if((player[i].color + player[counter].color == 3) &&
	 (i != counter)) {
	write_data(dsock[counter], names[i], 50);
	break;
      }
    }
    for(i = 0; i < PNUM; i++) {
      /* SUPER KLUDGE!!! */
      if(((player[i].color + player[counter].color == 4 ) ||
	  (player[i].color + player[counter].color == 2 )) &&
	 ( i != counter)){
	write_data(dsock[counter], names[i], 50);
	break;
      }
    }
  }
}

get_a_socket()
{
  static int counter=0;
  int dumcount;

  switch (select(FD_SETSIZE, &rfdset, 0, 0, NULL)) {
  case 0:
    fprintf (stderr,"select: timeout\n");
    break;
  case -1:
    perror ("select");
    break;
  default:
    for(counter=0 ; counter<PNUM ; ++counter) {
      if(FD_ISSET(dsock[counter],&rfdset)) {
	return(counter);
      }
    }
  }
  return(-2);
}

initplayers()
{
  int counter;
  for(counter=0;counter<PNUM;counter++) {
    player[counter].eptr=player[counter].pptr=player[counter].buffer;
    player[counter].pmesg=0;
    player[counter].color= -1;
  }
}

void end_game()
{
  int counter;
  puts("Ending Game");
  for(counter=0; counter < PNUM; counter++) close(dsock[counter]);
  exit(0);
}
