#ifndef SP_HW1_SERVER_H
#define SP_HW1_SERVER_H

#include "common.h"

#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define SVR_ACCEPT_HDR_LEN   7
#define SVR_REJECT_HDR_LEN   7

#define SVR_HOSTNAME_MAX   512
#define SVR_BUFFER_SIZE    512

typedef struct {
	char hostname[SVR_HOSTNAME_MAX];  // server's hostname
	unsigned short port;  // port to listen
	int listen_fd;  // fd to wait for a new connection
	char accept_hdr[SVR_ACCEPT_HDR_LEN + 1];
	char reject_hdr[SVR_REJECT_HDR_LEN + 1];
	fd_set readfds;
	fd_set writefds;
	fd_set exceptfds;
	ftab* file_table;
} server;

typedef struct {
	char host[SVR_HOSTNAME_MAX];  // client's host
	int conn_fd;  // fd to talk with client
	char buf[SVR_BUFFER_SIZE];  // data sent by/to client
	size_t buf_set;
	size_t buf_len;  // bytes used by buf
	char* filename;  // filename set in header, end with '\0'.
	int file_fd;	 // fd to read or write local file
	fnode* file_info;
	int active : 1;  // whether this conn_fd is active
	int header_done : 1;  // used by request_read to know if the header is done
	int header_accept : 1;  // used by procconn to know if ACCEPT/REJECT is sent
} request;

// initailize a server, exit for error
void server_init (server* svr, unsigned short port, int maxfd);

// free resources used by a server
void server_free (server* svr);

// initailize a request instance
void request_init (request* reqP);

// free resources used by a request instance
void request_free (request* reqP, server* svr);

// return 0: socket ended, request done.
// return 1: success, message (without header) got this time is in reqP->buf
// with reqP->buf_len bytes. read more until got <= 0. It's guaranteed that
// the header would be correctly set after the first read.
// error code:
// -1: client connection error
int request_read (request* reqP);
void request_msg (request* reqP, const char* format, ...);
void request_err (request* reqP, const char* key, int chkrval);

#endif /* SP_HW1_SERVER_H */