#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <assert.h>
#include "server.h"
#include "netutils.h"
#include "config.h"
#include "stats.h"

void server_response_loop(int sockfd, int response_size, int number_of_messages)
{
  struct sockaddr_in their_addr; /* connector's address information */
  socklen_t sin_size;
  int new_fd;
  char *dummy_message;
  char recv_buf[MAX_RECV_BUFFER_SIZE];
  int msg_count = 0;
  struct timeval tv, rtv, stv;
  struct timeval now_tv;
  
  double elapsed_time;
  int total_bytes = 0;
  int recv_bytes = 0;
  double *send_times;
  double *recv_times;
  double *wait_times;
  

  // allocate arrays for send and receive times
  if (number_of_messages > 0)
  {
    send_times = (double *)malloc(sizeof(double) * number_of_messages);
    assert(send_times);
    recv_times = (double *)malloc(sizeof(double) * number_of_messages);
    assert(recv_times);
  wait_times = (double *)malloc(sizeof(double) * number_of_messages);
  assert(wait_times);
  }
  else
  {
    send_times = (double *)malloc(sizeof(double) * 1);
    assert(send_times);
    recv_times = (double *)malloc(sizeof(double) * 1);
    assert(recv_times);
  wait_times = (double *)malloc(sizeof(double) * number_of_messages);
  assert(wait_times);
  }

  // create message for sending response
  dummy_message = form_dummy_message(response_size);

  // accept a new connection
  sin_size = sizeof(struct sockaddr_in);
  if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
    perror("accept");
    exit(1);
  }
  if (config.terse_debug) {
    fprintf(stderr, "server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
  }
  
  // get time across all messages
  get_time(&tv);

  while(number_of_messages == 0 || msg_count < number_of_messages) {  /* main accept() loop */

  	fd_set rfds;
	FD_ZERO(&rfds);
	FD_SET(new_fd, &rfds);

	// wait
    get_time(&rtv);
    select (new_fd + 1, &rfds, NULL, NULL, NULL);
    get_time(&now_tv);
    wait_times[msg_count] = get_time_elapsed(&now_tv, &rtv);

    // get time before receive
    get_time(&rtv);
    
    // receive request
    recv_bytes = recv_message(new_fd, recv_buf, MAX_RECV_BUFFER_SIZE);

    // get current time
  	get_time(&now_tv);

    // record receiving times
    recv_times[msg_count] = get_time_elapsed(&now_tv, &rtv);

    // get time before send
    get_time(&stv);
    
    // send response
    send_message(new_fd, dummy_message, response_size);

    // get current time
  	get_time(&now_tv);

    // record sending times
    send_times[msg_count] = get_time_elapsed(&now_tv, &stv);

    // increment total bytes
    total_bytes += response_size + recv_bytes;

    // increment number of requests sent
	if (number_of_messages > 0)
	{
      msg_count++;
	}
  }

    // get current time
  	get_time(&now_tv);

  // time across all messages
  elapsed_time = get_time_elapsed(&now_tv, &tv);

  // close connection
  shutdown(new_fd, 2);

  print_summary_stats(elapsed_time, total_bytes, number_of_messages);

  print_array_stats("Sending", send_times, number_of_messages, 
		    response_size, config.sending_verbose_stats);
  print_array_stats("Waiting", wait_times, number_of_messages, 
		    response_size, config.sending_verbose_stats);
  print_array_stats("Receiving", recv_times, number_of_messages, 
		    recv_bytes, config.receiving_verbose_stats);
  printf("\n");
  

}








