#ifndef LO_TYPES_H
#define LO_TYPES_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#ifdef HAVE_POLL
#include <poll.h>
#endif

#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#endif

#ifdef _MSC_VER
typedef SSIZE_T ssize_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
#endif

#include <pthread.h>

#include "lo/lo_osc_types.h"

typedef void (*lo_err_handler)(int num, const char *msg, const char *path);

struct _lo_method;

typedef struct _lo_address {
	char            *host;
	int              socket;
	char            *port;
	int              protocol;
	struct addrinfo *ai;
	int              errnum;
	const char      *errstr;
	int              ttl;
} *lo_address;

typedef struct _lo_blob {
	uint32_t  size;
	char     *data;
} *lo_blob;

typedef struct _lo_message {
	char      *types;
	size_t     typelen;
	size_t     typesize;
	void      *data;
	size_t     datalen;
	size_t     datasize;
	lo_address source;
        lo_arg   **argv;
        /* timestamp from bundle (LO_TT_IMMEDIATE for unbundled messages) */
        lo_timetag ts;
} *lo_message;

typedef int (*lo_method_handler)(const char *path, const char *types,
				 lo_arg **argv, int argc, struct _lo_message
				 *msg, void *user_data);

typedef struct _lo_method {
	const char        *path;
	const char        *typespec;
	lo_method_handler  handler;
	char              *user_data;
	struct _lo_method *next;
} *lo_method;

typedef struct _lo_server {
	struct addrinfo         *ai;
	lo_method                first;
	lo_err_handler           err_h;
	int	 	         port;
	char                   	*hostname;
	char                   	*path;
	int            	         protocol;
	void		        *queued;
	struct sockaddr_storage  addr;
	socklen_t 	         addr_len;
	int                  sockets_len;
	int                  sockets_alloc;
#ifdef HAVE_POLL
	struct pollfd        *sockets;
#else
	struct { int fd; }   *sockets;
#endif
} *lo_server;

typedef struct _lo_server_thread {
lo_server    s;
	pthread_t    thread;
	volatile int active;
	volatile int done;
} *lo_server_thread;

typedef struct _lo_bundle {
	size_t      size;
	size_t	    len;
	lo_timetag  ts;
	lo_message *msgs;
	char      **paths;
} *lo_bundle;

typedef struct _lo_strlist {
	char *str;
	struct _lo_strlist *next;
} lo_strlist;

typedef union {
    int32_t  i;
    float    f;
    char     c;
    uint32_t nl;
} lo_pcast32;
    
typedef union {
    int64_t    i;
    double     f;
    uint64_t   nl;
    lo_timetag tt;
} lo_pcast64;

extern struct lo_cs {
	int udp;
	int tcp;
} lo_client_sockets;
	
#endif
