// Please compile with:
// 	g++ -std=c++11 `pkg-config --cflags --libs glibmm-2.4 giomm-2.4`test.cc
// Then kill gvfsd-http before running, and monitor with:
// 	lsof -p $(pidof gvfsd-http)

#include <glibmm.h>
#include <giomm.h>

#include <iostream>

namespace {
	static const char *URL = "http://www.google.com/images/srpr/logo11w.png";
}

using Glib::ustring;
using Glib::RefPtr;

static RefPtr<Glib::MainLoop> main_loop = Glib::MainLoop::create ();

class RemoteLoader
{
public:
	RemoteLoader (const Glib::ustring& url)
	  : m_cancellable (Gio::Cancellable::create ())
	{
		std::cout << "Requesting " << url << std::endl;
		auto file = Gio::File::create_for_uri (url);
		auto callback = sigc::ptr_fun (&RemoteLoader::on_load);
            	file->load_contents_async (callback, m_cancellable);
	}

	~RemoteLoader ()
	{
		auto cancellable = m_cancellable;
		if (!cancellable) return;

		Glib::Thread *joinable = Glib::Thread::create ([cancellable] ()
		{	
			cancellable->cancel ();
			// No direct support for detached threads, so...
			Glib::Thread *self = Glib::Thread::self ();
			g_thread_unref (self->gobj ());
		});
	}

	static void on_load (const RefPtr<Gio::AsyncResult>& result)
	{
	        char *buf = nullptr;
        	gsize length = 0;

		const auto file = RefPtr<Gio::File>::cast_dynamic (result->get_source_object_base ());
		if (!file) return;

		try
		{
			bool success = file->load_contents_finish (result, buf, length);
			if (!success) 
			{
				std::cerr << "Not successful (" << file->get_uri () << ")" << std::endl;
			}
			else
			{
				std::cout << "Successful load (" << file->get_uri () << ")" << std::endl;
			}
	        }
	        catch (const Glib::Error& e)
        	{
			std::cerr << "Exception: " << e.what () << " when trying to load "
			          << file->get_uri () << std::endl;
		}

		g_free (buf);
	}


private:
	RefPtr<Gio::Cancellable> m_cancellable;
};


static bool
load_another ()
{
	static int how_many = 0;
	if (how_many > 9)
	{
		std::cout << "Exiting in 5 seconds... " << std::endl;
		Glib::signal_timeout ().connect_seconds_once ([] { main_loop->quit (); }, 5);
		return false;
	}
	
	for (int i = how_many*5; i < (how_many+1)*5; ++i)
	{
		std::ostringstream oss;
		oss << URL << "?nocache=" << i;
		auto loader = new RemoteLoader (oss.str ());
		Glib::signal_timeout ().connect_seconds_once ([loader] { delete loader; }, 5);
	}

	++how_many;
	return true;
}


int
main ()
{
	std::cout << " === Killing gvfsd-http === " << std::endl;
	system ("killall gvfsd-http");

	Gio::init ();
	Glib::signal_timeout ().connect_seconds (sigc::ptr_fun (&load_another), 1);
	main_loop->run ();

	std::string cmd = "bash -c 'pidof gvfsd-http | xargs lsof -p'";
	std::cout << "\n\n\t === Running " << cmd << " === \n" << std::endl;
	return system (cmd.c_str ());
}
