// 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).

#ifndef HPLAYLIST_H
#define HPLAYLIST_H

#include <kfiletreeview.h>
#include <kfileitem.h>
#include <kurl.h>
#include <noatun/playlist.h>
#include <qvaluestack.h>
#include <qwidget.h>

#include "branch.h"

class KPopupMenu;

namespace Hayes
{
// This class is tricky, as I have to ignore most of Noatun's old
// tag loading system, providing instead the great new KFileMetaInfo stuff.
//
// Though at the same time all the info must be available
class PlaylistItemData : public ::PlaylistItemData
{
public:
	PlaylistItemData(const KFileItem &);
	virtual ~PlaylistItemData(void);

	virtual QString property(const QString &, const QString & = 0) const;
	virtual void setProperty(const QString &, const QString &);
	virtual void clearProperty(const QString &);
	virtual QStringList properties(void) const;
	virtual bool isProperty(const QString &) const;
	virtual bool operator==(const PlaylistItemData &) const;

	const KFileItem &fileItem(void) const;

	virtual void remove(void) {};
private:
	KURL url;
	KFileItem *item;
	int len;
};

// This is an entirely filesystem-based playlist.
//
// It supplies you a view, because the view has the DirLister, and the Playlist
// needs the DirLister.
class Playlist : public ::Playlist
{
Q_OBJECT
public:
	Playlist(QWidget *viewParent, QWidget *listParent, const char * = "HayesView", const char * = "HayesPlaylist");

	FileTreeView *view(void) { return treeView; };

	void open(const KURL &);

	void setColumns(int a) { treeView->setColumns(a); };
	void setShuffle(bool);
	void setSaveVolume(bool);

	virtual void reset(void);
	virtual void clear(void) {/* rm -rf.. yeah right */};
	virtual void setCurrent(const PlaylistItem &);
	virtual void addFile(const KURL &, bool = false) {};
	virtual PlaylistItem next(void);
	virtual PlaylistItem current(void);
	virtual PlaylistItem previous(void);
	virtual PlaylistItem getFirst(void) const;
	virtual PlaylistItem getLast(void) const;
	virtual PlaylistItem getAfter(const PlaylistItem &) const;
	virtual PlaylistItem getBefore(const PlaylistItem &) const;

	FileTreeViewItem *viewItem(const PlaylistItem &) const;

	virtual bool listVisible(void) const
	{
		return ((QWidget *)parent())->isVisible();
	}

	virtual QValueList<PlaylistItem> select(const QStringList &, const QStringList &,
	                                        int, bool, bool) { return QValueList<PlaylistItem>(); };

	virtual QValueList<PlaylistItem> select(const QString &, const QString &,
	                                        int, bool, bool) { return QValueList<PlaylistItem>(); };

public slots:
	// hmm.. but I thought C casts were bad, mmkay?
	// I hope I don't end up in a ditch somewhere because of this.
	virtual void showList(void)
	{
		((QWidget *)parent())->show();
	}

	// This is just one little itsy bitsy area where C++ strong typing
	// is a nuisance.
	virtual void hideList(void)
	{
		((QWidget *)parent())->hide();
	}

signals:
	void busy(const QString &);
	void finished(const QString &, int);
	void newSong(PlaylistItem);

private slots:
	void populateBegin(void);
	void populateFinished(KFileTreeViewItem *);
	void executed(QListViewItem *);

private:
	FileTreeViewItem *getFirstItem(bool honorCheckBox, bool honorShuffle) const;
	FileTreeViewItem *getLastItem(bool honorCheckBox) const;
	FileTreeViewItem *getNextItem(FileTreeViewItem *, bool honorCheckBox, bool honorShuffle) const;
	FileTreeViewItem *getPreviousItem(FileTreeViewItem *, bool honorCheckBox, bool honorShuffle) const;
	void openItem(FileTreeViewItem *);

	void setCurrentItem(FileTreeViewItem *);

	static PlaylistItem makePlaylistItem(FileTreeViewItem *);
	FileTreeViewItem *findItem(KURL) const;
	FileTreeViewItem *findItem(PlaylistItem) const;

	KURL root;
	FileTreeView *treeView;
	Branch *myBranch;
	FileTreeViewItem *currentItem;
	FileTreeViewItem *itemToOpen;

	bool shuffle;
	// getAfter and getBefore are const, so to avoid having to have
	// two copies of the same get*Items, these must be mutable.
	typedef QValueStack<KURL> History;
	mutable History history;
	mutable History::Iterator historyPosition;

	bool saveVolume;
	bool firstTime;
};

}

#endif
