#include "network.h"
#include <qsocketnotifier.h>
#include <qtimer.h>

#include <kdebug.h>

#ifdef WITH_GGZ
Network *Network::self;
#endif

Network::Network()
: QObject()
{
#ifdef WITH_GGZ
	self = this;
	mod = NULL;
#endif
	m_sn = NULL;
	m_dsn = NULL;
}

Network::~Network()
{
#ifdef WITH_GGZ
	if(mod)
	{
		ggzmod_disconnect(mod);
		ggzmod_free(mod);
	}
#endif
}

void Network::connect()
{
#ifdef WITH_GGZ
	int fd;

	kdDebug() << "network::connect" << endl;

	if(mod) return;

	mod = ggzmod_new(GGZMOD_GAME);
	ggzmod_set_handler(mod, GGZMOD_EVENT_SERVER, &server_input);
#ifdef GGZMOD_VERSION_MICRO
#if GGZMOD_VERSION_MICRO >= 7
	ggzmod_set_handler(mod, GGZMOD_EVENT_PLAYER, &server_input);
#endif
#endif
	ggzmod_connect(mod);
	fd = ggzmod_get_fd(mod);

	m_sn = new QSocketNotifier(fd, QSocketNotifier::Read, this);
	QObject::connect(m_sn, SIGNAL(activated(int)), SLOT(slotDispatch()));

	if(!m_sn->isEnabled()) emit signalError();
	QTimer::singleShot(500, this, SLOT(slotDispatch()));
#endif
}

void Network::disconnect()
{
	if(m_sn)
	{
		delete m_sn;
		m_sn = NULL;
	}
	if(m_dsn)
	{
		delete m_dsn;
		m_dsn = NULL;
	}
}

void Network::slotInput(int fd)
{
	emit signalInput(fd);
}

#ifdef WITH_GGZ
void Network::server_input(GGZMod *mod, GGZModEvent e, const void *data)
{
	int fd;

	kdDebug() << "network::server_input" << endl;
	switch(e)
	{
		case GGZMOD_EVENT_SERVER:
			fd = *(int*)data;
			kdDebug() << "network: server event!" << endl;
			ggzmod_set_state(mod, GGZMOD_STATE_PLAYING);
			self->serverInput(fd);
			break;
#ifdef GGZMOD_VERSION_MICRO
#if GGZMOD_VERSION_MICRO >= 7
		case GGZMOD_EVENT_PLAYER:
			kdDebug() << "network: player event!" << endl;
			kdDebug() << "network: is spectator? " << ((int*)data)[0] << endl;
			kdDebug() << "network: num " << ((int*)data)[1] << endl;
			break;
#if GGZMOD_VERSION_MICRO >= 11
		case GGZMOD_EVENT_CHAT:
		case GGZMOD_EVENT_STATS:
#endif
#if GGZMOD_VERSION_MICRO >= 12
		case GGZMOD_EVENT_INFO:
#endif
		case GGZMOD_EVENT_STATE:
		case GGZMOD_EVENT_SEAT:
		case GGZMOD_EVENT_SPECTATOR_SEAT:
		case GGZMOD_EVENT_ERROR:
			kdDebug() << "network: discard unhandled event" << endl;
			break;
#endif
#endif
	}
}
#endif

void Network::serverInput(int fd)
{
	m_channel = fd;

	m_dsn = new QSocketNotifier(fd, QSocketNotifier::Read, this);
	QObject::connect(m_dsn, SIGNAL(activated(int)), SLOT(slotInput(int)));
}

void Network::slotDispatch()
{
#ifdef WITH_GGZ
	kdDebug() << "network::slotdispatch" << endl;
	ggzmod_dispatch(mod);

	if(!m_sn->isEnabled()) emit signalError();
#endif
}

int Network::channel()
{
	return m_channel;
}

long Network::generator()
{
	static long gen = 0;

	return ++gen;
}

