#include <openconnect.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct vpn_session_info {
	long auth_expiration;
	int lifetime_secs;
	long user_expires;
	int lifetime_warning_prior;
	const char *lifetime_warning_message;
} vpn_session_info;

typedef void (*vpn_connected_callback)(int cmd_pipe_fd,
				       const vpn_session_info *session_info,
				       void *user_data);

typedef struct vpn_options {
	void *user_data;

	const char *server;
	const char *cookie;

	const char *user_agent;
	const char *os;
	const char *os_version;
	const char *client_version;
	const char *host_id;
	const char *local_hostname;

	const char *script;
	const char *interface;
	const int script_tun;

	const char *certificate;
	const char *sslkey;
	const char *key_password;
	const char *servercert;

	const uid_t csd_uid;
	const char *csd_wrapper;

	const int reconnect_timeout;
	const int mtu;
	const int disable_ipv6;
	const int no_dtls;

	const int dpd_interval;
	const int no_xmlpost;
} vpn_options;

int vpn_connect(const vpn_options *options, vpn_connected_callback callback);
void vpn_disconnect();

extern void vpn_log(int level, const char *msg);

static char *format_message(const char *format, va_list args)
{
	va_list args_copy;
	va_copy(args_copy, args);
	int len = vsnprintf(NULL, 0, format, args_copy);
	va_end(args_copy);

	char *buffer = (char *)malloc(len + 1);
	if (buffer == NULL) {
		return NULL;
	}

	vsnprintf(buffer, len + 1, format, args);
	return buffer;
}

static void _log(int level, ...)
{
	va_list args;
	va_start(args, level);

	char *format = va_arg(args, char *);
	char *message = format_message(format, args);

	va_end(args);

	if (message == NULL) {
		vpn_log(PRG_ERR, "Failed to format log message");
	} else {
		vpn_log(level, message);
		free(message);
	}
}

#define LOG(level, ...) _log(level, __VA_ARGS__)
#define ERROR(...) LOG(PRG_ERR, __VA_ARGS__)
#define INFO(...) LOG(PRG_INFO, __VA_ARGS__)
#define DEBUG(...) LOG(PRG_DEBUG, __VA_ARGS__)
#define TRACE(...) LOG(PRG_TRACE, __VA_ARGS__)
