/****************************************************************************
**
** Copyright (C) 2006-2008 fullmetalcoder <fullmetalcoder@hotmail.fr>
**
** This file is part of the Edyuk project <http://edyuk.org>
** 
** This file may be used under the terms of the GNU General Public License
** version 2 as published by the Free Software Foundation and appearing in the
** file GPL.txt included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "qsingleapplication.h"

#include "qmanagedrequest.h"
#include "qinterprocesschannel.h"

#include <QStringList>

/*!
	\brief Constructor
*/
QSingleApplication::QSingleApplication(int& argc, char **argv, bool useGui)
 : QApplication(argc, argv, useGui)
{
	pChannel = new QInterProcessChannel(this);
	
	connect(pChannel, SIGNAL( message(QString) ),
			this	, SLOT  ( message(QString) ) );
	
	connect(pChannel, SIGNAL( request(QStringList) ),
			this	, SLOT  ( request(QStringList) ) );
	
	setMessagingPolicy(Signals);
	setInstanciationPolicy(None);
}

/*!
	\brief Destructor
*/
QSingleApplication::~QSingleApplication()
{
	pChannel->close();
}

/*!
	\return Wheter the creation of an instance is allowed.
*/
bool QSingleApplication::isInstanceAllowed() const
{
	return pChannel->isServer();
}

/*!
	\return The current messaging policy
*/
QSingleApplication::MessagingPolicy QSingleApplication::messagingPolicy() const
{
	return m_messaging;
}

/*!
	\brief Sets the messaging policy
	
	\see messagingPolicy()
*/
void QSingleApplication::setMessagingPolicy(MessagingPolicy p)
{
	m_messaging = p;
}

/*!
	\return The current instanciation policy
*/
QSingleApplication::InstanciationPolicy QSingleApplication::instanciationPolicy() const
{
	return m_instanciation;
}

/*!
	\brief Sets the instanciation policy
	
	\see instanciationPolicy()
*/
void QSingleApplication::setInstanciationPolicy(InstanciationPolicy p)
{
	m_instanciation = p;
}

/*!
	\brief Launchs the application if allowed
	
	\see instanciationPolicy()
*/
int QSingleApplication::exec()
{
	int ret = -1;
	
	if ( isInstanceAllowed() )
	{
		ret = QApplication::exec();
		
	} else {
		
		switch ( instanciationPolicy() )
		{
			case ForwardArguments :
				qWarning("QSingleApplication : forwarding parameters");
				sendRequest(arguments());
				break;
				
			default:
				qWarning("QSingleApplication : all instances already occupied");
				break;
		}
	}
	
	return ret;
}

/*!
	\overload
*/
void QSingleApplication::sendRequest(const QString& s)
{
	sendRequest(QStringList(s));
}

/*!
	\brief sends a message to the running instance of the application
	
	\param l A list of arguments that make up a request to be sent.
*/
void QSingleApplication::sendRequest(const QStringList& l)
{
	if ( !pChannel || l.isEmpty() )
		return;
	
	/*
	qDebug("sending message to %s:%i over TCP/IP : \"%s\"",
			qPrintable(pManager->address().toString()),
			pManager->port(),
			msg.constData());
	*/
	
	pChannel->sendMessage(QManagedRequest::joinArguments("--request", l));
}

/*!
	\internal
*/
void QSingleApplication::message(const QString& s)
{
	if ( s.isEmpty() )
		return;
	
	switch ( messagingPolicy() )
	{
		case Events :
			
			/*
			QRequestEvent *e = new QRequestEvent(s);
			postEvent(s);
			*/
			
			break;
			
		case Signals :
			emit request(s);
			break;
			
		default:
			break;
	}
}

/*!
	\internal
*/
void QSingleApplication::request(const QStringList& l)
{
	if ( l.isEmpty() )
		return;
	
	switch ( messagingPolicy() )
	{
		case Events :
			
			/*
			QRequestEvent *e = new QRequestEvent(s);
			postEvent(s);
			*/
			
			break;
			
		case Signals :
			emit request(l.join(" | "));
			break;
			
		default:
			break;
	}
}

/*!
	\internal
*/
bool QSingleApplication::event(QEvent *e)
{
	return QApplication::event(e);
}
