// Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com>
//
// 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 <kaction.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kdialog.h>
#include <keditcl.h>
#include <kedittoolbar.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <kpropertiesdialog.h>
#include <kstatusbar.h>
#include <kstdaction.h>
#include <kstandarddirs.h>
#include <kurldrag.h>
#include <qfileinfo.h>
#include <qframe.h>
#include <qheader.h>
#include <qlayout.h>
#include <qurl.h>

#include "cmodule.h"
#include "playlist.h"
#include "window.h"
#include <noatun/player.h>

#include <cassert>

extern "C" Plugin *create_plugin()
{
	return new Hayes::Window;
}

Hayes::Window *Hayes::Window::rutherford = 0;

Hayes::Window::Window()
	: KMainWindow(0, "Hayes")
	, Plugin()
	, dirMenu(new KPopupMenu(this))
	, menu(new KPopupMenu(this))
	, contextItem(0)
{
	rutherford = this;

	(void)KStdAction::open(this, SLOT(file_open()), actionCollection());
	(void)KStdAction::close(this, SLOT(close()), actionCollection());
	(void)KStdAction::find(this, SLOT(edit_find()), actionCollection());
	options_toolbarAction = KStdAction::showToolbar(this, SLOT(options_toolbar()), actionCollection());
	options_menubarAction = KStdAction::showMenubar(this, SLOT(options_menubar()), actionCollection());
	options_statusbarAction = KStdAction::showStatusbar(this, SLOT(options_statusbar()), actionCollection());
	options_shuffleAction = new KToggleAction(i18n("&Shuffle"), 0, this, SLOT(options_shuffle()), actionCollection(), "options_shuffle");
	options_volumeAction = new KToggleAction(i18n("Save &Volume"), 0, this, SLOT(options_volume()), actionCollection(), "options_volume");
	(void)KStdAction::preferences(napp, SLOT(preferences()), actionCollection());
	(void)KStdAction::configureToolbars(this, SLOT(options_configuretoolbars() ), actionCollection(), "configuretoolbars");

	createGUI("hayesui.rc");

	list = new Hayes::Playlist(this, this);
	assert(list);

	currentSong = new QLabel(statusBar());
	statusBar()->addWidget(currentSong);
	statusBar()->show();
	newSong(0);
	connect(list, SIGNAL(busy(const QString &)), statusBar(), SLOT(message(const QString &)));
	connect(list, SIGNAL(finished(const QString &, int)), statusBar(), SLOT(message(const QString &, int)));
	connect(list, SIGNAL(newSong(PlaylistItem)), this, SLOT(newSong(PlaylistItem)));

	connect(list->view(), SIGNAL(contextMenu(KListView *, QListViewItem *, const QPoint &)), this, SLOT(contextMenu(KListView *, QListViewItem *, const QPoint &)));
	menu->insertItem(i18n("Properties..."), this, SLOT(properties(void)));
	dirMenu->insertItem(i18n("Properties..."), this, SLOT(properties(void)));
	dirMenu->insertItem(i18n("Open in browser..."), this, SLOT(openInBrowser(void)));
}

Hayes::Window::~Window()
{
	KConfig &config = *KGlobal::config();
	saveMainWindowSettings(&config, "Hayes Window");
	config.setGroup("Hayes");
	config.writeEntry("currentPlaylistURL", currentPlaylistURL.url(-1));
	config.writeEntry("shuffle", options_shuffleAction->isChecked());
	config.writeEntry("volume", options_volumeAction->isChecked());

	list->view()->superSaveLayout(&config, "Hayes ListView");

	delete list;
	list = 0;
}

void Hayes::Window::init(void)
{
	setCentralWidget(list->view());

	hide();

	// this has to come after the load, because of the modified flag
	KConfig &config = *KGlobal::config();

	applyMainWindowSettings(&config, "Hayes Window");
	options_statusbarAction->setChecked( !statusBar()->isHidden() );
	options_toolbarAction->setChecked( !toolBar("mainToolBar")->isHidden() );
	options_menubarAction->setChecked( config.readBoolEntry("menuShown", true) );

	currentPlaylistURL = KURL();
	config.setGroup("Hayes");

	options_shuffleAction->setChecked(config.readBoolEntry("shuffle", false));
	options_shuffle();

	options_volumeAction->setChecked(config.readBoolEntry("volume", false));
	options_volume();

	list->view()->superRestoreLayout(&config, "Hayes ListView");

	Hayes::CModule *module = new Hayes::CModule(this);
	module->reopen();
	module->save();

	// this must be last, specificly the open().  The open() enters a new loop
	QString playlistURL = config.readEntry("currentPlaylistURL", QString::null);
	if(!playlistURL.isEmpty())
	{
		currentPlaylistURL = KURL(playlistURL);
		setCaption(currentPlaylistURL.prettyURL());
		list->open(currentPlaylistURL);
	}
	else
	{
		setCaption(i18n("Playlist"));
	}
}

Playlist *Hayes::Window::playlist(void)
{
	return list;
}

void Hayes::Window::setColumns(int columns)
{
	list->setColumns(columns);
}

void Hayes::Window::closeEvent(QCloseEvent *)
{
	if(list) list->hideList();
	hide();
}

void Hayes::Window::hideEvent(QHideEvent *e)
{
	KMainWindow::hideEvent(e);
}

void Hayes::Window::showEvent(QShowEvent *e)
{
	if(list) list->showList();
	KMainWindow::showEvent(e);
}

void Hayes::Window::search(void)
{
	bool done = false;
	bool found = false;

	while(!done)
	{
		if(!findCurrent)
		{
			if(findDialog->get_direction())
			{
				// backward
				if(KMessageBox::Yes == KMessageBox::questionYesNo(findDialog,
				   i18n("Beginning of document reached.\nContinue from the end?"),
				   i18n("Find"))
				)
				{
					findCurrent = list->getFirst();
				}
				else
				{
					findCurrent = list->getLast();
					done = true;
				}
			}
			else
			{
				// forward
				if(KMessageBox::Yes == KMessageBox::questionYesNo(findDialog,
				   i18n("End of document reached.\nContinue from the beginning?"),
				   i18n("Find"))
				)
				{
					findCurrent = list->getFirst();
				}
				else
				{
					findCurrent = list->getLast();
					done = true;
				}
			}
		}

		kdDebug(66666) << "find: " << findCurrent.title() << endl;
		KFileTreeViewItem *item = list->viewItem(findCurrent);
		assert(item);
		for(int i = 0; i < list->view()->columns() && !found; i++)
		{
			if(item->text(i).contains(findDialog->getText(), findDialog->case_sensitive()))
			{
				list->view()->clearSelection();
				list->view()->setSelected(item, true);
				list->view()->ensureItemVisible(item);
				found = true;
				done = true;
			}
		}

		if(!findDialog->get_direction())
			findCurrent = list->getAfter(findCurrent); // forward
		else
			findCurrent = list->getBefore(findCurrent); // backward
	}

	if(!found) KMessageBox::information(findDialog, i18n("Text not found."), i18n("Find"));
}

void Hayes::Window::searchDone(void)
{
	napp->exit_loop();
}

void Hayes::Window::newSong(PlaylistItem item)
{
	QString cap = i18n("Not Playing");
	if(item) cap = item.title();
	currentSong->setText(cap);
}

void Hayes::Window::contextMenu(KListView *, QListViewItem *qitem, const QPoint &point)
{
	contextItem = dynamic_cast<KFileTreeViewItem *>(qitem);
	if(!contextItem) return;
	if(contextItem->isDir())
		dirMenu->popup(point);
	else
		menu->popup(point);
}

void Hayes::Window::properties(void)
{
	assert(contextItem);
	(void)new KPropertiesDialog(contextItem->fileItem());
}

void Hayes::Window::openInBrowser(void)
{
	assert(contextItem);
	kapp->invokeBrowser(contextItem->fileItem()->url().url());
}

void Hayes::Window::file_open(void)
{
	KURL url = KFileDialog::getExistingDirectory();
	if(!url.isEmpty())
	{
		currentPlaylistURL = url;
		list->open(currentPlaylistURL);
		setCaption(currentPlaylistURL.prettyURL());

		// save here for more predictable behavior
		KConfig &config = *KGlobal::config();
		config.setGroup("Hayes");
		config.writeEntry("currentPlaylistURL", currentPlaylistURL.url(-1));
		config.sync();
	}
}

void Hayes::Window::edit_find(void)
{
	findCurrent = list->current();
	if(!findCurrent) findCurrent = list->getFirst();

	findDialog = new KEdFind(this);
	connect(findDialog, SIGNAL(search()), this, SLOT(search()));
	connect(findDialog, SIGNAL(done()), this, SLOT(searchDone()));

	// enter loop
	findDialog->exec();

	// after loop is done
	delete findDialog;
}

void Hayes::Window::options_shuffle(void)
{
	list->setShuffle(options_shuffleAction->isChecked());
}

void Hayes::Window::options_volume(void)
{
	list->setSaveVolume(options_volumeAction->isChecked());
}

void Hayes::Window::options_toolbar(void)
{
	if(options_toolbarAction->isChecked())
		toolBar("mainToolBar")->show();
	else
		toolBar("mainToolBar")->hide();
}

void Hayes::Window::options_menubar(void)
{
	if(options_menubarAction->isChecked())
		menuBar()->show();
	else
		menuBar()->hide();
}

void Hayes::Window::options_statusbar(void)
{
	if(options_statusbarAction->isChecked())
		statusBar()->show();
	else
		statusBar()->hide();
}

void Hayes::Window::options_configuretoolbars(void)
{
	KEditToolbar dlg(actionCollection(), "hayesui.rc");
	if(dlg.exec())
		createGUI("hayesui.rc");
}

#include "window.moc"
