/***************************************************************************
    copyright            : (C) 2004 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

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

#ifndef PLAYLIST_COLLECTION_H
#define PLAYLIST_COLLECTION_H

#include "playlistinterface.h"
#include "stringhash.h"
#include "jukIface.h"

#include <tdeshortcut.h>
#include <tdelocale.h>
#include <kdirlister.h>

#include <tqguardedptr.h>

class TQWidgetStack;
class TDEAction;
class Playlist;
class PlaylistItem;
class HistoryPlaylist;
class UpcomingPlaylist;
class SearchPlaylist;
class DynamicPlaylist;

typedef TQValueList<Playlist *> PlaylistList;
typedef TQValueList<PlaylistItem *> PlaylistItemList;

class PlaylistCollection : public PlaylistInterface, CollectionIface
{
    friend class Playlist;
    friend class CollectionList;
    friend class DynamicPlaylist;

    static PlaylistCollection *m_instance;

public:
    PlaylistCollection(TQWidgetStack *playlistStack);
    virtual ~PlaylistCollection();

    static PlaylistCollection *instance() { return m_instance; }

    virtual TQString name() const;
    virtual FileHandle currentFile() const;
    virtual int count() const;
    virtual int time() const;
    virtual void playNext();
    virtual void playPrevious();
    virtual void stop();
    virtual bool playing() const;

    void playFirst();
    void playNextAlbum();

    virtual TQStringList playlists() const;
    virtual void createPlaylist(const TQString &name);
    virtual void createDynamicPlaylist(const PlaylistList &playlists);
    virtual void showMore(const TQString &artist, const TQString &album = TQString());
    virtual void removeTrack(const TQString &playlist, const TQStringList &files);

    virtual TQString playlist() const;
    virtual TQString playingPlaylist() const;
    virtual void setPlaylist(const TQString &playlist);

    virtual TQStringList playlistTracks(const TQString &playlist) const;
    virtual TQString trackProperty(const TQString &file, const TQString &property) const;
    virtual TQPixmap trackCover(const TQString &file, const TQString &size = "Small") const;

    virtual void open(const TQStringList &files = TQStringList());
    virtual void open(const TQString &playlist, const TQStringList &files);
    virtual void addFolder();
    virtual void rename();
    virtual void duplicate();
    virtual void save();
    virtual void saveAs();
    virtual void remove() = 0;
    virtual void reload();
    virtual void editSearch();
    virtual void setDynamicListsFrozen(bool) = 0;

    bool showMoreActive() const;
    void clearShowMore(bool raise = true);
    void enableDirWatch(bool enable);

    void removeItems();
    void refreshItems();
    void renameItems();
    void addCovers(bool fromFile);
    void removeCovers();
    void viewCovers();
    void showCoverManager();

    virtual PlaylistItemList selectedItems();

    void scanFolders();

    void createPlaylist();
    void createSearchPlaylist();
    void createFolderPlaylist();

    void guessTagFromFile();
    void guessTagFromInternet();

    void setSearchEnabled(bool enable);

    HistoryPlaylist *historyPlaylist() const;
    void setHistoryPlaylistEnabled(bool enable);

    UpcomingPlaylist *upcomingPlaylist() const;
    void setUpcomingPlaylistEnabled(bool enable);

    void dirChanged(const TQString &path);

    /**
     * Returns a pointer to the action handler.
     */
    TQObject *object() const;

    void newItems(const KFileItemList &list) const;

    /**
     * This is the current playlist in all things relating to the player.  It
     * represents the playlist that either should be played from or is currently
     * playing.
     */
    virtual Playlist *currentPlaylist() const;

    /**
     * This is the currently visible playlist and should be used for all user
     * interaction elements.
     */
    virtual Playlist *visiblePlaylist() const;

    /**
     * Makes \a playlist the currently visible playlist.
     */
    virtual void raise(Playlist *playlist);

    /**
     * This is used to put up a temporary widget over the top of the playlist
     * stack.  This is part of a trick to significantly speed up painting by
     * hiding the playlist to which items are being added.
     */
    void raiseDistraction();
    void lowerDistraction();

    class ActionHandler;

protected:
    virtual TQWidgetStack *playlistStack() const;
    virtual void setupPlaylist(Playlist *playlist, const TQString &iconName);
    virtual void removePlaylist(Playlist *playlist) = 0;

    bool importPlaylists() const;
    bool containsPlaylistFile(const TQString &file) const;

    TQString playlistNameDialog(const TQString &caption = i18n("Create New Playlist"),
                               const TQString &suggest = TQString(),
                               bool forceUnique = true) const;
    TQString uniquePlaylistName(const TQString &suggest = i18n("Playlist")) const;

    void addNameToDict(const TQString &name);
    void addFileToDict(const TQString &file);
    void removeNameFromDict(const TQString &name);
    void removeFileFromDict(const TQString &file);

    Playlist *playlistByName(const TQString &name) const;

private:
    void readConfig();
    void saveConfig();

    TQWidgetStack     *m_playlistStack;
    HistoryPlaylist  *m_historyPlaylist;
    UpcomingPlaylist *m_upcomingPlaylist;
    ActionHandler    *m_actionHandler;

    KDirLister  m_dirLister;
    StringHash  m_playlistNames;
    StringHash  m_playlistFiles;
    TQStringList m_folderList;
    bool        m_importPlaylists;
    bool        m_searchEnabled;
    bool        m_playing;

    TQGuardedPtr<SearchPlaylist> m_showMorePlaylist;
    TQGuardedPtr<Playlist> m_belowShowMorePlaylist;
    TQGuardedPtr<DynamicPlaylist> m_dynamicPlaylist;
    TQGuardedPtr<Playlist> m_belowDistraction;

    TQWidget *m_distraction;
};

/**
 * This class is just used as a proxy to handle the signals coming from action
 * activations without requiring PlaylistCollection to be a TQObject.
 */

class PlaylistCollection::ActionHandler : public TQObject
{
    TQ_OBJECT
  
public:
    ActionHandler(PlaylistCollection *collection);

private:
    TDEAction *createAction(const TQString &text,
                          const char *slot,
                          const char *name,
                          const TQString &icon = TQString(),
                          const TDEShortcut &shortcut = TDEShortcut());
private slots:
    void slotPlayFirst()     { m_collection->playFirst(); }
    void slotPlayNextAlbum() { m_collection->playNextAlbum(); }

    void slotOpen()         { m_collection->open(); }
    void slotAddFolder()    { m_collection->addFolder(); }
    void slotRename()       { m_collection->rename(); }
    void slotDuplicate()    { m_collection->duplicate(); }
    void slotSave()         { m_collection->save(); }
    void slotSaveAs()       { m_collection->saveAs(); }
    void slotReload()       { m_collection->reload(); }
    void slotRemove()       { m_collection->remove(); }
    void slotEditSearch()   { m_collection->editSearch(); }

    void slotRemoveItems()  { m_collection->removeItems(); }
    void slotRefreshItems() { m_collection->refreshItems(); }
    void slotRenameItems()  { m_collection->renameItems(); }
    void slotScanFolders()  { m_collection->scanFolders(); }

    void slotViewCovers()   { m_collection->viewCovers(); }
    void slotRemoveCovers() { m_collection->removeCovers(); }
    void slotAddLocalCover()    { m_collection->addCovers(true); }
    void slotAddInternetCover() { m_collection->addCovers(false); }

    void slotCreatePlaylist()       { m_collection->createPlaylist(); }
    void slotCreateSearchPlaylist() { m_collection->createSearchPlaylist(); }
    void slotCreateFolderPlaylist() { m_collection->createFolderPlaylist(); }

    void slotGuessTagFromFile()     { m_collection->guessTagFromFile(); }
    void slotGuessTagFromInternet() { m_collection->guessTagFromInternet(); }

    void slotSetSearchEnabled(bool enable)           { m_collection->setSearchEnabled(enable); }
    void slotSetHistoryPlaylistEnabled(bool enable)  { m_collection->setHistoryPlaylistEnabled(enable); }
    void slotSetUpcomingPlaylistEnabled(bool enable) { m_collection->setUpcomingPlaylistEnabled(enable); }
    void slotShowCoverManager()                      { m_collection->showCoverManager(); }
    void slotEnableDirWatch(bool enable)             { m_collection->enableDirWatch(enable); }
    void slotDirChanged(const TQString &path)         { m_collection->dirChanged(path); }

    void slotNewItems(const KFileItemList &list)     { m_collection->newItems(list); }

signals:
    void signalSelectedItemsChanged();
    void signalCountChanged();

private:
    PlaylistCollection *m_collection;
};

#endif
