// systray.h
//
// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com>
// Copyright (C) 1999 Charles Samuels <charles@kde.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name(s) of the author(s) shall not be
// used in advertising or otherwise to promote the sale, use or other dealings
// in this Software without prior written authorization from the author(s).

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <noatun/effects.h>
#include <noatun/app.h>
#include <noatun/pref.h>
#include <noatun/player.h>
#include "systray.h"
#include "kitsystemtray.h"
#include <noatun/stdaction.h>
#include "cmodule.h"

#include <kaction.h>
#include <kconfig.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpassivepopup.h>
#include <kpixmapeffect.h>
#include <kpopupmenu.h>
#include <kstdaction.h>
#include <qbitmap.h>
#include <qpainter.h>
#include <qtimer.h>
#include <qtooltip.h>

#include <qimage.h>
#include <kurl.h>
#include <kio/netaccess.h>
#include <kdebug.h>
#include <kstandarddirs.h>

#define COVER_MAXW 128 // TODO: Maybe make this value configurable?
#define COVER_MAXH 128
#define BASEICON "noatun"

NoatunSystray *NoatunSystray::jasonkb = 0;

NoatunSystray::NoatunSystray()
	: KMainWindow()
	, Plugin()
	, trayStatus(0), trayBase(0), mTray(0)
	, mPassivePopup(0L)
{
	hide();

	tmpCoverPath = locateLocal("tmp", "youngHickoryCover.png");
	removeCover(); // make sure any old temp cover is gone

	KStdAction::quit(napp, SLOT(quit()), actionCollection());
	KStdAction::open(napp, SLOT(fileOpen()), actionCollection());
	KStdAction::preferences(napp, SLOT(preferences()), actionCollection());
	mBack = NoatunStdAction::back(actionCollection(), "back");
	mStop = NoatunStdAction::stop(actionCollection(), "stop");
	mPlay = NoatunStdAction::playpause(actionCollection(), "play");
	mForward = NoatunStdAction::forward(actionCollection(), "forward");
	mPlaylist = NoatunStdAction::playlist(actionCollection(), "show_playlist");
	NoatunStdAction::loop(actionCollection(), "loop_style");
	NoatunStdAction::effects(actionCollection(), "effects");
	NoatunStdAction::equalizer(actionCollection(), "equalizer");

	createGUI("systrayui.rc");

	mTray = new KitSystemTray("tray", this);
	mTray->show();

	trayBase = renderIcon(BASEICON, QString::null);
	trayStatus = renderIcon(BASEICON, "player_stop");

	mTray->changeTitle(*trayBase, "Noatun");
	showingTrayStatus = false;

	blink = Neither;
	mBlinkTimer = new QTimer(this, "mBlinkTimer");
	connect(mBlinkTimer, SIGNAL(timeout()), this, SLOT(slotBlinkTimer()));

	connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlaying()));
	connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped()));
	connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPaused()));
	napp->player()->handleButtons();

	jasonkb = this;
}

NoatunSystray::~NoatunSystray()
{
	kdDebug(66666) << k_funcinfo << "Called." << endl;
	disconnect(napp->player(), 0, 0, 0);
	removeCover();
	delete trayBase;
	delete trayStatus;
	napp->showInterfaces();
}

void NoatunSystray::init()
{
	new YHModule(this);
	slotBlinkTimer();
}

void NoatunSystray::setBlink(Blink b)
{
//	kdDebug(66666) << k_funcinfo << "Called, b=" << (int)b << endl;

	if(blink==b) return;

	blink = b;

	if (blink == BlinkIcon)
		mBlinkTimer->start(1000);
	else
		mBlinkTimer->stop();

	slotBlinkTimer();
}

void NoatunSystray::setTip(bool b)
{
	tip = b;
	if(tip)
		QToolTip::add(mTray, tipText);
	else
		QToolTip::remove(mTray);
}

void NoatunSystray::closeEvent(QCloseEvent*)
{
	kdDebug(66666) << k_funcinfo << "Called." << endl;
	unload();
}

void NoatunSystray::slotPlaying()
{
	mStop->setEnabled(true);
	changeTray("player_play");
	const PlaylistItem item = napp->player()->current();
	QString text = item.title();
	if ( item.length() > 0 )
		text += QString::fromLatin1("\n") + i18n("Length: %1").arg( item.lengthString() );
	setTipText( text );
}

void NoatunSystray::slotStopped()
{
	if(!napp->player()->current())
		return;
	changeTray("player_stop");
	setTipText(i18n("Stopped"));
}

void NoatunSystray::slotPaused()
{
	changeTray("player_pause");
	setTipText(i18n("%1 - Paused").arg(napp->player()->current().title()));
}

void NoatunSystray::changeTray(const QString &pm)
{
	delete trayStatus;
	trayStatus = renderIcon(BASEICON, pm);
	if(showingTrayStatus) slotBlinkTimer();
}

void NoatunSystray::slotBlinkTimer()
{
//	kdDebug(66666) << k_funcinfo << "Called, blink=" << (int)blink << endl;

	switch((int)blink)
	{
		case BlinkIcon:
			showingTrayStatus ^= true;
			break;
		case ShowIcon:
			showingTrayStatus = true;
			break;
		case Neither:
			showingTrayStatus = false;
			break;
	}

	if(showingTrayStatus)
		mTray->setPixmap(*trayStatus);
	else
		mTray->setPixmap(*trayBase);
}

// taken from patched karamba xmmssensor
// modified heavily to work in this place
void NoatunSystray::updateCover()
{
// 	kdDebug(66666) << k_funcinfo << endl;
	QString dir = napp->player()->current().url().directory();
	QString cover;

	// TODO: Maybe make these filenames configurable?
	if(QFile::exists(dir + "/folder.png"))
		cover = dir + "/folder.png";
	else if(QFile::exists(dir + "/.folder.png"))
		cover = dir + "/.folder.png";
	else if(QFile::exists(dir + "/cover.png"))
		cover = dir + "/cover.png";
	else if(QFile::exists(dir + "/cover.jpg"))
		cover = dir + "/cover.jpg";
	else if(QFile::exists(dir + "/cover.jpeg"))
		cover = dir + "/cover.jpeg";
	else // no cover
	{
//		kdDebug(66666) << k_funcinfo << "NO COVER" <<  endl;
		removeCover();
		return;
	}

	QString title = napp->player()->current().title();

	QImage previmg;
	previmg.load(tmpCoverPath);

	if(previmg.text("Title") != title)
	{ //Verify song change to limit CPU usage
//		kdDebug(66666) << k_funcinfo << "Creating new temp cover for '" <<
//			cover << "'" << endl;

		QImage src;
		QImage tmpimg;
		src.load(cover);

		if(src.width() >= COVER_MAXW || src.height() >= COVER_MAXH)
			tmpimg = src.scale(COVER_MAXW, COVER_MAXH, QImage::ScaleMin);
		else
			tmpimg = src;

		tmpimg.setText("Title", 0, title); //add Title in the image text for cache usage
		tmpimg.save(tmpCoverPath, "PNG", 0);
	}
}

void NoatunSystray::removeCover()
{
	if(QFile::exists(tmpCoverPath))
	{
//		kdDebug(66666) << k_funcinfo << "Deleting temp cover file" << endl;
		KIO::NetAccess::del(KURL(tmpCoverPath), this);
	}
}

void NoatunSystray::setShowCovers(bool show)
{
	mShowCovers = show;
	if (!show)
		removeCover();
}

void NoatunSystray::setTipText(const QString& text)
{
	if(text == tipText) // save the planet, save cpu cycles ;)
		return;

	tipText = text;

	if(tip) QToolTip::add(mTray, tipText);

	if(mPassivePopup)
	{
		if (mShowCovers)
			updateCover();
		QTimer::singleShot(0, this, SLOT(showPassivePopup()));
	}
}

void NoatunSystray::showPassivePopup()
{
	mPassivePopup->reparent(0L, QPoint(0,0));

	if(mShowCovers && QFile::exists(tmpCoverPath) && !napp->player()->isStopped())
		mPassivePopup->setView(i18n("Noatun"), tipText, QPixmap(tmpCoverPath));
	else
		mPassivePopup->setView(i18n("Noatun"), tipText);

	mPassivePopup->show();
}

void NoatunSystray::setPassivePopup(bool pop)
{
	if ( pop == (mPassivePopup != 0L) )
		return;

	if (pop)
	{
		mPassivePopup = new KPassivePopup(mTray, "passive popup");
	}
	else
	{
		delete mPassivePopup;
		mPassivePopup = 0L;
	}
}

QPixmap *NoatunSystray::renderIcon(const QString& baseIcon, const QString &overlayIcon) const
{
	QPixmap *base = new QPixmap(KSystemTray::loadIcon(baseIcon));

	if(!(overlayIcon.isNull())) // otherwise leave the base as-is
	{
		QPixmap overlay = KSystemTray::loadIcon(overlayIcon);
		if(!overlay.isNull())
		{
			// first combine the masks of both pixmaps (in case both actually have one)
			if((overlay.mask()!=0) && (base->mask()!=0))
			{
				QBitmap mask = *(base->mask());
				bitBlt(&mask, 0, 0, const_cast<QBitmap *>(overlay.mask()),
					0, 0, overlay.width(), overlay.height(), Qt::OrROP);
				base->setMask(mask);
			}
			// draw the overlay on top of it
			QPainter p(base);
			p.drawPixmap(0, 0, overlay);
		}
	}
	return base;
}
#include "systray.moc"
