#ifndef _NETWORK_H_
#define _NETWORK_H_

#ifdef WIN32
  #include <winsock2.h>
  #define ioctl ioctlsocket
#endif

#ifndef WIN32
  typedef int SOCKET;
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/time.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netinet/tcp.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <sys/ioctl.h>
#endif

#define DEFAULT_PORT  5980
#define MSG_LEN       500
#define MSG_HEADLEN   4
#define MAX_CLIENTS   2

#if defined(__BIG_ENDIAN) && !defined(__LITTLE_ENDIAN)
#define htons(A)  (A)
#define htonl(A)  (A)
#define ntohs(A)  (A)
#define ntohl(A)  (A)

#elif defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
#define htons(A)  ((((int)(A) & 0xff00) >> 8) | \
                   (((int)(A) & 0x00ff) << 8))
#define ntohs     htons
#define ntohl     htonl

#else
#error "Either __BIG_ENDIAN or __LITTLE_ENDIAN must be #defined, but not both."
#endif

#define write_byte(x, y, z) (*(byte *)&x[y++] = (byte)z)
#define read_byte(x, y, z) (z = *(byte *)&x[y++])
#define write_short(x, y, z) {*((u_short *)((byte *)&x[y])) = htons(z); y += 2;}
#define read_short(x, y, z)  {z = ntohs(*(u_short *)((byte *)&x[y])); y += 2;}

/* network message types */
enum {
  PACKET_INVALID = -1,
  PACKET_SERVER_FULL,
  PACKET_USER_BANNED,
  PACKET_CLIENT_JOIN,
  PACKET_CLIENT_LOGIN,
  PACKET_LOGINOK,
  PACKET_LOGINERROR,
  PACKET_CLIENT_CHAT
};

typedef struct packet {
  struct packet *next;
  byte *buffer;
  int type;
} packet;

typedef struct clientState {
  SOCKET socket;
  int quited;
  int connected;
  packet *queue;
} clientState;

int wsock_init(void);

int client_connect(clientState **client, const char *host, u_short port);

void client_addPacket(clientState **client, int type, char *data);

void client_sendall(clientState *client);

void client_cleanqueue(clientState *client);

/* reads packet from client and returns a new packet */
packet *packet_read(clientState *cs);

u_long resolve_host(const char *hostname);

#endif
