/***************************************************************************
                noatuninterface.cpp  -  Interface to access Noatun
                             -------------------
    begin                : Mon Jan 15 21:09:00 CEST 2001
    copyright            : (C) 2000-2002 by Stefan Gehn
    email                : sgehn@gmx.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "noatunInterface.h"
#include "noatunInterface.moc"

#include <kdebug.h>
#include <qstringlist.h>
#include <qstrlist.h>

#define TIMER_FAST  250

NoatunInterface::NoatunInterface() : PlayerInterface()
{
	mTimerValue = TIMER_FAST;
	mNoatunTimer = new QTimer ( this, "mNoatunTimer" );

	connect(mNoatunTimer, SIGNAL(timeout()), SLOT(updateSlider()) );
	kapp->dcopClient()->setNotifications ( true );

	connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)),
		SLOT(appRegistered(const QCString&)) );

	connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)),
		SLOT(appRemoved(const QCString&)));

	QTimer::singleShot(0, this, SLOT(myInit()));
}

NoatunInterface::~NoatunInterface()
{
	kapp->dcopClient()->setNotifications(false);
	delete mNoatunTimer;
}

void NoatunInterface::myInit(void)
{
	// Start the timer if noatun is already running
	// Needed if user adds applet while running noatun
	if ( findRunningNoatun() )
	{
		emit playerStarted();
		mNoatunTimer->start(mTimerValue);
	}
	else
	{
		emit playerStopped();
		emit newSliderPosition(0,0);
	}
}

void NoatunInterface::appRegistered ( const QCString &appId )
{
	if(appId.contains("noatun",false) )
	{
		mAppId = appId;
		emit playerStarted();
		mNoatunTimer->start(mTimerValue);
	}
}

void NoatunInterface::appRemoved ( const QCString &appId )
{
	if ( appId.contains("noatun",false) )
	{
	 	// is there still another noatun alive?
		if ( findRunningNoatun() )
			return;
		mNoatunTimer->stop();
		emit playerStopped();
		emit newSliderPosition(0,0);
	}
}

void NoatunInterface::updateSlider ( void )
{
	// length/time in msecs, -1 means "no playobject in noatun"
	int len, time;
	QByteArray data, replyData;
	QCString replyType;

	if (!kapp->dcopClient()->call(mAppId, "Noatun", "length()",data, replyType, replyData))
	{
		//kdDebug() << "mediacontrol: DCOP communication Error" << endl;
		// -2 is an internal errornumber, might be used later
		len = -2;
	}
	else
	{
		QDataStream reply(replyData, IO_ReadOnly);
		if (replyType == "int")
		{
			reply >> len;
		}
		else
		{
			//kdDebug() << "mediacontrol: unexpected type of DCOP-reply" << endl;
			// -3 is an internal errornumber, might be used later
			len = -3;
		}
	}

	data = 0;
	replyData = 0;
	replyType = 0;

	if (!kapp->dcopClient()->call(mAppId, "Noatun", "position()",data, replyType, replyData))
	{
		//kdDebug() << "mediacontrol: DCOP communication error" << endl;
		time = -2;
	}
	else
	{
		QDataStream reply(replyData, IO_ReadOnly);
		if (replyType == "int")
		{
			reply >> time;
		}
		else
		{
			//kdDebug() << "mediacontrol: unexpected type of DCOP-reply" << endl;
			time = -3;
		}
	}

//	kdDebug() << "NoatunInterface::updateSlider()  len  = " << len << endl;
//	kdDebug() << "NoatunInterface::updateSlider()  time = " << time << endl;

	if ( (time < 0) || (len < 0)) // Noatun isn't playing and thus returns -1
	{
		len = 0;
		time = 0;
	}
	emit ( newSliderPosition(len/1000,time/1000) );
}

// Drag-n-Drop stuff =================================================================

void NoatunInterface::dragEnterEvent(QDragEnterEvent* event)
{
//	kdDebug() << "NoatunInterface::dragEnterEvent()" << endl;
	event->accept( QUriDrag::canDecode(event) );
}

void NoatunInterface::dropEvent(QDropEvent* event)
{
//	kdDebug() << "NoatunInterface::dropEvent()" << endl;
	QStrList uri;
	if (QUriDrag::decode(event, uri))
	{
//		for (char *file=uri.first(); file != 0; file=uri.next() )
//			kdDebug() << "uri: " << file << endl;
		QByteArray data;
		QDataStream arg(data, IO_WriteOnly);
		arg << QStringList::fromStrList(uri) << false;
		if (!kapp->dcopClient()->send(mAppId, "Noatun", "addFile(QStringList,bool)",data))
			kdDebug() << "Couldn't send drop to noatun" << endl;
	}
}

// ====================================================================================

void NoatunInterface::sliderStartDrag()
{
	mNoatunTimer->stop();
}

void NoatunInterface::sliderStopDrag()
{
	mNoatunTimer->start(mTimerValue);
}

void NoatunInterface::jumpToTime( int sec )
{
	QByteArray data;
	QDataStream arg(data, IO_WriteOnly);
	arg << (sec*1000);  // noatun wants milliseconds
	kapp->dcopClient()->send(mAppId, "Noatun", "skipTo(int)", data);
}

void NoatunInterface::play()
{
	QByteArray data;
	kapp->dcopClient()->send(mAppId, "Noatun", "play()", data);
}

void NoatunInterface::pause()
{
	QByteArray data;
	kapp->dcopClient()->send(mAppId, "Noatun", "playpause()", data);
}

void NoatunInterface::stop()
{
	QByteArray data;
	kapp->dcopClient()->send(mAppId, "Noatun", "stop()", data);
}

void NoatunInterface::next()
{
	QByteArray data;
	// try both calls, fastForward() is noatun from kde2
//	if  ( !kapp->dcopClient()->send("noatun", "Noatun", "fastForward()", data) )
	kapp->dcopClient()->send(mAppId, "Noatun", "forward()", data);
}

void NoatunInterface::prev()
{
	QByteArray data;
	kapp->dcopClient()->send(mAppId, "Noatun", "back()", data);
}

const QString NoatunInterface::getTrackTitle() const
{
	QString title;
	QByteArray data, replyData;
	QCString replyType;
	if (!kapp->dcopClient()->call(mAppId, "Noatun", "title()",data, replyType, replyData))
	{
		//kdDebug() << "mediacontrol: DCOP communication Error" << endl;
		return QString("");
	}
	else
	{
		QDataStream reply(replyData, IO_ReadOnly);
		if (replyType == "QString")
		{
			reply >> title;
			return title;
		}
		else
		{
			//kdDebug() << "mediacontrol: unexpected type of DCOP-reply" << endl;
			return QString("");
		}
	}
}

// FIXME: what if we have a dcop app named, let's say, 'noatunfrontend'?
bool NoatunInterface::findRunningNoatun()
{
	QCStringList allApps = kapp->dcopClient()->registeredApplications();
	QValueList<QCString>::iterator iterator;

	for (iterator = allApps.begin(); iterator != allApps.end(); iterator++)
	{
		if ((*iterator).contains("noatun",false))
		{
			mAppId = *iterator;
			return true;
		}
	}
	return false;
}
