/*
 * game.c
 * Programmers:
 *   Ernest Kim
 *   Grace Lin
 *   Joseph Kim
 * CS320
 * Final Project
 */

#include "game.h"

Player *HEAD, *cur_player;

void game_play (Player *head) {
  fd_set fd_read;
  int maxfd, len;
  Player *current, *prev;
  struct timeval timeout;
  char buf[BUF_SIZE];
  int num, x, y;

  FD_ZERO(&fd_read);
  HEAD = head;
  maxfd = -1;
  timeout.tv_sec = 0;
  timeout.tv_usec = 250000;

  logic_initialize();

  for (num = 0, current = HEAD; current != NULL; 
       current = current->next, num++) {
    FD_SET(current->client_fd, &fd_read);
    if (current->client_fd > maxfd) maxfd = current->client_fd;
    current->id_num = num;
    
    for (x=0; x<7; x++) 
      logic_Random_Tile(&current->tiles[x]);
    current->tiles[7] = '\0';
    sprintf (buf, "6:%s\n", current->tiles);
    game_write_player (current, buf);
  }


  game_write_all("Server","Starting new game");
  cur_player = HEAD;
  
  while (1) {
    select (maxfd+1, &fd_read, NULL, NULL, NULL);
    select (0, NULL, NULL, NULL, &timeout);

    for (prev = NULL, current = HEAD; current != NULL; current = current->next) {    
      if (FD_ISSET(current->client_fd, &fd_read)) {
	len = read(current->client_fd, buf, BUF_SIZE-1);
	if (len == 0) {
	  /* Adjust the linked list */
	  if (prev==NULL) 
	    HEAD = current->next;
	  else 
	    prev->next = current->next;

	  /* Clean up */
	  close (current->client_fd);
	  FD_CLR (current->client_fd, &fd_read);
	  if (maxfd == current->client_fd) {
	    maxfd = -1;
	    game_recalc_maxfd(&maxfd);
	  }

	  game_write_all(current->name, "logged off");
	  free(current);
	  num--;
	  if (num == 0) {
	    exit (0);
	  }

	  continue;
	}

	else if  (len > 0) {
	  buf[len]='\0';
	  game_parse (current, buf);
	  game_buf_init (buf);
	}

	else {
	  perror ("game.c error after read");
	  printf ("buffer: %sn", buf);
	}
      }
      
      FD_SET (current->client_fd, &fd_read);
      prev = current;
    }
  }
}


void game_recalc_maxfd(int *maxfd) {
  Player *current;

  for (current = HEAD; current != NULL; current = current->next) {
    if (current->client_fd > *maxfd) *maxfd = current->client_fd;
  }
}


void game_parse (Player *sender, char *buf) {
  char *last, *last2;
  char *comm;
  char message[BUF_SIZE];
  int dir, x, y;
  char *tiles;

  buf = strtok(buf, "\r\n");

  strtok_r (buf, ":", &last);

  if (strcmp(buf, I_SET_NAME) == 0) {
    /* Set the player's name */
    sender->name = strdup (last);
    sprintf(message, "logged in from %s ", sender->hostname);
    game_write_all(last, message);
    return;
  }


  else if (strcmp (buf, I_CHAT) == 0) {
    /* Chat message */
    game_write_all(sender->name, last);
    return;
  }

  else if (strcmp (buf, I_PLACE_WORD) == 0) {
    /* Place a word */
    dir = atoi(strtok_r(last, ":", &last));
    x = atoi(strtok_r(last, ":", &last));
    y = atoi(strtok_r(last, ":", &last));
    tiles = strdup(strtok_r(last, ":", &last));
    if ((logic_Tile_Placement(dir, sender->tiles, x, y, tiles)) &&
	(cur_player == sender)) {
      sprintf(message, "4:%d:%d:%d:%s\n", dir, x, y, tiles);
      game_write_mesg(message);
      if (cur_player->next == NULL) cur_player = HEAD;
      else cur_player = cur_player->next;

      sprintf (buf, "6:%s\n", sender->tiles);
      game_write_player (sender, buf);
    }

    else if (cur_player != sender) {
      sprintf(message, "4:-1:Error, it'snot your turn\n");
      game_write_player(sender, message);
    }

    else {
      sprintf(message, "4:-1:Tiles won't place\n");
      game_write_player(sender, message);
    }

    return;
  }

  else if (strcmp (buf, I_CHALLENGE) == 0) {
    /* The word was challenged */
    return;
  }

  else if (strcmp (buf, I_TRADE) == 0) {
    /* Trade for tiles */
    tiles = strdup(strtok_r(last, ":", &last));    
    if (cur_player != sender) {
      sprintf(message, "4:-1:Not your turn\n");
      game_write_player(sender, message);
      return;
    }

    else {
      if (logic_trade_tiles(sender->tiles, tiles)) {
	sprintf(message, "6:%s", sender->tiles);
	game_write_player(sender, message);
	return;
      }
      
      else {
	sprintf(message, "6:-1:You do not have some of the tiles that you wanted to trade");
	game_write_player(sender, message);
	return;
      }
    }
  }
}

void game_write_player(Player *sender, char *message) {
  write (sender->client_fd, message, strlen(message));
}


void game_write_all (char *from, char *mesg) {
  Player *current;
  char obuf[BUF_SIZE];

  sprintf (obuf, "3:%s: %s\n", from, mesg);

  for (current = HEAD; current != NULL; current = current->next) 
    write (current->client_fd, obuf, strlen(obuf));
}

void game_write_mesg (char *mesg) {
  Player *current;

  for (current = HEAD; current != NULL; current = current->next) 
    write (current->client_fd, mesg, strlen(mesg));
}





void game_buf_init (char *buf) {
  int x;

  for (x=0; x< BUF_SIZE; x++) 
    buf[x]=0;
}


