#include <stdio.h>
#include "jrb.h"
#include "socketfun.h"
#include <pthread.h>

typedef struct {
  char *name;
  int age;
  char *ssn;
} Entry;

JRB t;
int tsize;
pthread_mutex_t lock;

void *server_thread(void *v)
{
  int *fdp;
  JRB tmp;
  FILE *fin, *fout;
  int age;
  char fn[300], ln[300], ssn[100], n[300];
  char *buffer;
  char command[300];
  Entry *e;
  int i;

  fdp = (int *)v;
  fin = fdopen(*fdp, "r");
  if (fin == NULL) { perror("making fin"); exit(1); }
  fout = fdopen(*fdp, "w");
  if (fout == NULL) { perror("making fout"); exit(1); }

  while(fscanf(fin, "%s", command) != EOF) {
    if (strcmp(command, "ADD") == 0) {
      fscanf(fin, "%s %s %d %s", fn, ln, &age, ssn);
      e = (Entry *) malloc(sizeof(Entry));
      e->name = (char *) malloc(sizeof(char)*(strlen(ln)+strlen(fn)+3));
      strcpy(e->name, ln);
      strcat(e->name, ", ");
      strcat(e->name, fn);
      e->ssn = (char *) strdup(ssn);
      e->age = age;
      pthread_mutex_lock(&lock);
      jrb_insert_str(t, e->name, new_jval_v(e));
      tsize++;
      pthread_mutex_unlock(&lock);
    } else if (strcmp(command, "PRINT") == 0) {
      pthread_mutex_lock(&lock);
      buffer = (char *) malloc(sizeof(char)*(tsize)*(52));
      i = 0;
      jrb_traverse(tmp, t) {
        e = (Entry *) tmp->val.v;
        sprintf(buffer+(i*51), "%-30s -- %11s %4d\n", e->name, e->ssn, e->age);
        i++;
      }
      pthread_mutex_unlock(&lock);
      fprintf(fout, "__________________________________________________\n");
      fprintf(fout, "%s", buffer);
      fprintf(fout, "--------------------------------------------------\n");
      fflush(fout);
      free(buffer);
    } else if (strcmp(command, "DELETE") == 0) {
      fscanf(fin, "%s %s", fn, ln);
      strcpy(n, ln);
      strcat(n, ", ");
      strcat(n, fn);
      pthread_mutex_lock(&lock);
      tmp = jrb_find_str(t, n);
      if (tmp == NULL) {
        fprintf(fout, "Error: No %s %s\n", fn, ln);
        fflush(fout);
      } else {
        jrb_delete_node(tmp);
        tsize--;
      }
      pthread_mutex_unlock(&lock);
    } else if (strcmp(command, "DONE") == 0) {
      close(*fdp);
      free (fdp);
      return NULL;
    } else {
      fprintf(fout, "Bad command: %s\n", command);
      fflush(fout);
    }
  }
  close(*fdp);
  free (fdp);
  return NULL;
}
    
main(int argc, char **argv)
{
  pthread_t *tidp;
  int fd, *fdp;
  int sock;
  
  if (argc != 3) {
    fprintf(stderr, "usage: ssnserver1 host port\n");
    exit(1);
  }
 
  t = make_jrb();
  tsize = 0;
  sock = serve_socket(argv[1], atoi(argv[2]));
  pthread_mutex_init(&lock, NULL);

  while (1) {
    fd = accept_connection(sock);
    fdp = (int *) malloc(sizeof(int));
    *fdp = fd;
    tidp = (pthread_t *) malloc(sizeof(pthread_t));
    pthread_create(tidp, NULL, server_thread, fdp);
  }
  pthread_exit(NULL);
}

