// userinterface.cpp
//
// 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 <effects.h>
#include <noatunapp.h>
#include "controls.h"
#include "noatunpref.h"
#include "player.h"
#include "userinterface.h"
#include "noatunstdaction.h"

#include <kbuttonbox.h>
#include <kconfig.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kpixmapeffect.h>
#include <kpopupmenu.h>
#include <kstdaction.h>
#include <kwin.h>
#include <qbitmap.h>
#include <qdragobject.h>
#include <qlayout.h>
#include <qlcdnumber.h>
#include <qobjcoll.h>
#include <qpushbutton.h>
#include <qtooltip.h>
#include <qvbox.h>

Noatun::Noatun() : KMainWindow(), UserInterface()
{
	NOATUNPLUGINC(Noatun);
	setAcceptDrops(true);

	KStdAction::quit(napp, SLOT(quit()), actionCollection());
	KStdAction::open(napp, SLOT(fileOpen()), actionCollection());
	mToolbar = KStdAction::showToolbar(this, SLOT(showToolbar()), actionCollection());
	mMenubar = KStdAction::showMenubar(this, SLOT(showMenubar()), 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");
	mVolume = new KToggleAction(i18n("Show &Volume Control"), 0, this, SLOT(showVolumeControl()), actionCollection(), "show_volumecontrol");
	mLoop = new KAction(i18n("L&oop Style"), 0, napp->player(), SLOT(loop()), actionCollection(), "loop_style");
	NoatunStdAction::effects(actionCollection(), "effects");
	NoatunStdAction::equalizer(actionCollection(), "equalizer");
	mLoop->setIconSet(BarIconSet("noatunloopnone"));

	createGUI("excellentui.rc");

	menuBar()->insertItem(i18n("&Plugins"), napp->pluginMenu(), -1, 3);
	toolBar("mainToolBar")->hide();

	// Who needs Qt Designer?
	mainFrame = new QHBox(this);
	mainFrame->setSpacing(KDialog::spacingHint());
	mainFrame->setMargin(KDialog::marginHint());
	mSeeker = new L33tSlider(0,1000,100,0, L33tSlider::Horizontal, mainFrame);
	mElapsed = new QLCDNumber(5, mainFrame);
	mElapsed->setSegmentStyle(QLCDNumber::Flat);
	mElapsed->setFrameStyle(QFrame::Panel);
	mElapsed->setFrameShadow(QFrame::Sunken);
	mElapsed->setFixedWidth(mElapsed->width());
	mElapsed->setFixedHeight(mElapsed->height());
	mElapsed->display("");
	
	setCentralWidget(mainFrame);

	mTotal = new QLCDNumber(5, statusBar());
	mTotal->setSegmentStyle(QLCDNumber::Flat);
	mTotal->display("");
	statusBar()->addWidget(mTotal, 0, true);
	statusBar()->show();

	connect( napp->player(), SIGNAL(hideYourself()), this, SLOT(hide()) );
	connect( napp->player(), SIGNAL(showYourself()), this, SLOT(show()) );

	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();
	
	connect(napp->player(), SIGNAL(timeout()), this, SLOT(slotTimeout()));
	connect(napp->player(), SIGNAL(loopTypeChange(int)), this, SLOT(changeLoopType(int)));

	connect(seeker(), SIGNAL(userChanged(int)), napp->player(), SLOT(skipTo(int)));
	connect(seeker(), SIGNAL(sliderMoved(int)), SLOT(sliderMoved(int)));

	// Why + 25?  so the last button doesn't get cut off after a loop mode change
	// Better would be for toolbar icons to resize themselves when needed, then I
	// could dynamically catch a signal and resize the window as appropriate.
	setPlainCaption("Noatun");
	setIcon(SmallIcon("noatun"));
	changeLoopType(Player::None);
	if(napp->playlist()->current())
		changeStatusbar(napp->playlist()->current()->title());
	handleLengthString("00:00/00:00");

	KConfig *config = KGlobal::config();
	config->setGroup("excellent");
	
	toolBar("main")->setBarPos( (KToolBar::BarPosition)config->readLongNumEntry("mainBarPos", KToolBar::Top) );
	toolBar("main")->enable( (KToolBar::BarStatus)config->readLongNumEntry("mainEnable", KToolBar::Show) );
	toolBar("main")->setIconText( (KToolBar::IconText)config->readLongNumEntry("mainIconText", KToolBar::IconTextBottom) );
	mToolbar->setChecked( config->readBoolEntry("mainShown", true) );
	showToolbar();

	mVolumeControl = 0;
	mVolume->setChecked( config->readBoolEntry("volumeShown", false) );
	showVolumeControl();

	mMenubar->setChecked( config->readBoolEntry("menuShown", true) );
	showMenubar();

	if(config->readLongNumEntry("width"))
		resize(config->readLongNumEntry("width"), config->readLongNumEntry("height"));
	else
		resize( toolBar("main")->sizeHint().width() + 25, minimumHeight() );

	switch((NET::MappingState)config->readNumEntry("mappingState", (int)NET::Visible))
	{	
	case NET::Withdrawn:
//		hide();
		showNormal();	
		break;
	case NET::Visible:
		showNormal();
		break;
	case NET::Iconic:
		showMinimized();
		break;
	}
}

Noatun::~Noatun()
{
}

void Noatun::closeEvent(QCloseEvent *)
{
	KConfig *config = KGlobal::config();
	config->setGroup("excellent");
	config->writeEntry("mainBarPos", toolBar("main")->barPos());
	config->writeEntry("mainEnable", toolBar("main")->isEnabled());
	config->writeEntry("mainIconText", toolBar("main")->iconText());
	config->writeEntry("mainShown", mToolbar->isChecked());
	config->writeEntry("volumeShown", mVolume->isChecked());
	config->writeEntry("menuShown", mMenubar->isChecked());
	config->writeEntry("width", width());
	config->writeEntry("height", height());
	config->writeEntry("mappingState", (int)KWin::info(winId()).mappingState);
	config->sync();

	unload();
}

void Noatun::showEvent(QShowEvent *e)
{
	KConfig *config = KGlobal::config();
	config->setGroup("excellent");
	config->writeEntry("mappingState", (int)KWin::info(winId()).mappingState);
	config->sync();

	KMainWindow::showEvent(e);
}

void Noatun::hideEvent(QHideEvent *e)
{
	KConfig *config = KGlobal::config();
	config->setGroup("excellent");
	config->writeEntry("mappingState", (int)KWin::info(winId()).mappingState);
	config->sync();

	KMainWindow::hideEvent(e);
}

void Noatun::dragEnterEvent(QDragEnterEvent *event)
{
    // accept uri drops only
    event->accept(QUriDrag::canDecode(event));
}

void Noatun::dropEvent(QDropEvent *event)
{
	QStrList uri;
	if (QUriDrag::decode(event, uri))
	{
		for (char *file=uri.first(); file != 0; file=uri.next() )
			napp->player()->openFile(KURL(file), false);
	}
}

void Noatun::slotPlaying()
{
	changeStatusbar(napp->player()->current()->title());
	mStop->setEnabled(true);
	mPlay->setIconSet(BarIconSet("noatunpause"));
	mPlay->setText(i18n("Pause"));
}

void Noatun::slotStopped()
{
	if (!napp->player()->current()) return;
	changeStatusbar(napp->player()->current()->title());
	mStop->setEnabled(false);
	seeker()->setValue(0);
	mPlay->setIconSet(BarIconSet("noatunplay"));
	mPlay->setText(i18n("Play"));
	handleLengthString("00:00/00:00");
}

void Noatun::slotPaused()
{
	changeStatusbar(napp->player()->current()->title());
	mStop->setEnabled(true);
	mPlay->setIconSet(BarIconSet("noatunplay"));
	mPlay->setText(i18n("Play"));
}

void Noatun::slotTimeout()
{
	if(mVolumeControl)
		mVolumeControl->setValue(100 - napp->player()->volume());
	if (!napp->player()->current()) return;
	if (static_cast<L33tSlider*>(seeker())->currentlyPressed()) return;
	if (seeker())
		seeker()->setValue(napp->player()->getTime());
	handleLengthString(napp->player()->lengthString());
}

void Noatun::sliderMoved(int mille)
{
	if(napp->player()->current())
		handleLengthString(napp->player()->lengthString(napp->player()->current()->fromMille(mille)));
}

void Noatun::changeLoopType(int t)
{
	static const int time = 2000;
	switch (t)
	{
	case Player::None:
		statusBar()->message(i18n("No looping"), time);
		mLoop->setIconSet(BarIconSet("noatunloopnone"));
		mLoop->setText(i18n("No looping"));
		break;
	case Player::Song:
		statusBar()->message(i18n("Song looping"), time);
		mLoop->setIconSet(BarIconSet("noatunloopsong"));
		mLoop->setText(i18n("Song looping"));
		break;
	case Player::Playlist:
		statusBar()->message(i18n("Playlist looping"), time);
		mLoop->setIconSet(BarIconSet("noatunlooplist"));
		mLoop->setText(i18n("Playlist looping"));
	}
}

void Noatun::showToolbar(void)
{
	if(mToolbar->isChecked())
		toolBar("main")->show();
	else
		toolBar("main")->hide();
}

void Noatun::showMenubar(void)
{
	if(mMenubar->isChecked())
		menuBar()->show();
	else
		menuBar()->hide();
}

void Noatun::showVolumeControl(void)
{
	if(mVolume->isChecked())
		growVolumeControl();
	else
		shrinkVolumeControl();
}

void Noatun::changeCaption(const QString& text)
{
	setCaption(text);
}

void Noatun::changeStatusbar(const QString& text)
{
	statusBar()->message(!text.isNull() ? text : napp->player()->current()->title());
}

void Noatun::handleLengthString(const QString &text)
{
	QString elapsed = text.left(5);
	QString total = text.right(5);
	mElapsed->display(elapsed);
	mTotal->display(total);
}

void Noatun::growVolumeControl(void)
{
	mVolumeControl = new L33tSlider(0, 100, 10, 0, Vertical, mainFrame);
	mVolumeControl->setValue(100 - napp->player()->volume());
	mVolumeControl->show();
	connect(mVolumeControl, SIGNAL(sliderMoved(int)), this, SLOT(changeVolume(int)));
	connect(mVolumeControl, SIGNAL(userChanged(int)), this, SLOT(changeVolume(int)));
}

void Noatun::shrinkVolumeControl(void)
{
	if(mVolumeControl)
	{
		delete mVolumeControl;
		mVolumeControl = 0;
	}
}

void Noatun::changeVolume(int slider)
{
	napp->player()->setVolume(100 - slider);
}

#include "userinterface.moc"
