/* gcc `pkg-config --cflags --libs libsoup-2.4 glib-2.0` test-soup.c -g -O0 -o test-soup && ./test-soup */

#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <libsoup/soup.h>

static GCancellable *cancellable;

static void
abort_soup_session_cb (GCancellable *cancellable,
		       SoupSession *soup_session)
{
	soup_session_abort (soup_session);
}

static gboolean
quit_loop_cb (gpointer user_data)
{
	g_main_loop_quit (user_data);
	return FALSE;
}

static void
network_event_cb (SoupMessage *msg,
		  GSocketClientEvent event,
		  GIOStream *connection,
		  gpointer user_data)
{
	printf ("   %s: handshaking:%d (%x) is tls:%d (%s)\n", __FUNCTION__, event == G_SOCKET_CLIENT_TLS_HANDSHAKING, event, G_IS_TLS_CONNECTION (connection), connection ? G_OBJECT_TYPE_NAME (connection) : "null");
}

static gpointer
test_thread (gpointer user_data)
{
	GMainLoop *loop = user_data;
	SoupMessage *soup_message;
	SoupSession *soup_session;
	gulong cancel_id;
	guint status;

	soup_session = soup_session_new_with_options (
		SOUP_SESSION_PROXY_RESOLVER, NULL,
		NULL);

	soup_message = soup_message_new (SOUP_METHOD_GET, "https://wis.fit.vutbr.cz");
	g_signal_connect (soup_message, "network-event", G_CALLBACK (network_event_cb), NULL);

	cancel_id = g_cancellable_connect (
		cancellable,
		G_CALLBACK (abort_soup_session_cb),
		g_object_ref (soup_session),
		(GDestroyNotify) g_object_unref);

	status = soup_session_send_message (soup_session, soup_message);

	if (cancel_id > 0)
		g_cancellable_disconnect (cancellable, cancel_id);

	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
		GTlsCertificateFlags cert_flags = 0;

		g_object_get ((GObject *) soup_message,
			"tls-errors", &cert_flags,
			NULL);

		printf ("%s: Failed, certflags:%x code:%d reason:%s\n", __FUNCTION__, cert_flags, soup_message->status_code, soup_message->reason_phrase);
	} else
		printf ("%s: Success (%*s)\n", __FUNCTION__, (int)soup_message->response_body->length, soup_message->response_body->data);

	g_object_unref (soup_message);
	g_object_unref (soup_session);

	g_timeout_add_seconds (2, quit_loop_cb, loop);

	return NULL;
}

static gboolean
do_cancel (gpointer user_data)
{
	//g_cancellable_cancel (user_data);
	return FALSE;
}

static gboolean
start_thread (gpointer user_data)
{
	GThread *thread;

	thread = g_thread_new (NULL, test_thread, user_data);
	g_thread_unref (thread);

	g_timeout_add (100, do_cancel, cancellable);

	return FALSE;
}

int main (int argc, char *argv[])
{
	GMainLoop *loop;

	printf ("Hello...\n");

	g_type_init ();

	cancellable = g_cancellable_new ();

	loop = g_main_loop_new (NULL, FALSE);
	g_idle_add (start_thread, loop);
	g_main_loop_run (loop);
	g_main_loop_unref (loop);

	g_object_unref (cancellable);

	printf ("Bye...\n");

	return 0;
}
