/***************************************************************************
 * copyright            : (c) 2004 Pierpaolo Di Panfilo                    *
 *                        (c) 2004 Mark Kretschmann <markey@web.de>        *
 *                        (c) 2005-2006 Seb Ruiz <me@sebruiz.net>          *
 *                        (c) 2005 Gábor Lehel <illissius@gmail.com>       *
 *                        (c) 2006 Adam Pigg <adam@piggz.co.uk>           *
 * See COPYING file for licensing information                              *
 ***************************************************************************/

#ifndef PLAYLISTBROWSER_H
#define PLAYLISTBROWSER_H

#include "amarokconfig.h"
#include "amarok_export.h"
#include "playlistbrowseritem.h"
#include "podcastsettings.h"

#include <tdeaction.h>
#include <tdelistview.h>
#include <kpushbutton.h>
#include <kurl.h>
#include <tqdom.h>
#include <tqptrlist.h>
#include <tqvbox.h>

class KTextBrowser;
class TDEToolBar;

class TQCustomEvent;
class TQColorGroup;
class TQDragObject;
class TQPainter;
class TQPixmap;
class TQPoint;
class TQSplitter;
class TQTimer;

class HTMLView;
class InfoPane;
class PlaylistBrowserView;
class PlaylistTrackItem;


class PlaylistBrowser : public TQVBox
{
    TQ_OBJECT

    friend class DynamicMode;
    friend class PlaylistBrowserView;

    friend class PlaylistBrowserEntry;
    friend class PlaylistCategory;
    friend class PlaylistEntry;
    friend class PlaylistTrackItem;
    friend class PodcastChannel;  //for changing podcast timer list
    friend class PodcastEpisode;
    friend class DynamicEntry;
    friend class StreamEntry;
    friend class SmartPlaylist;


    public:
        enum AddMode  { PLAYLIST, PLAYLIST_IMPORT, STREAM, SMARTPLAYLIST, PODCAST, ADDDYNAMIC };

        ~PlaylistBrowser();

        void setInfo( const TQString &title, const TQString &info );

        void addStream( TQListViewItem *parent = 0 );
        void addSmartPlaylist( TQListViewItem *parent = 0 );
        void addDynamic( TQListViewItem *parent = 0 );
        void addPlaylist( const TQString &path, TQListViewItem *parent = 0, bool force=false, bool imported=false );
        PlaylistEntry *findPlaylistEntry( const TQString &url, TQListViewItem *parent=0 ) const;
        int  loadPlaylist( const TQString &playlist, bool force=false );

        void addPodcast( TQListViewItem *parent = 0 );
        LIBAMAROK_EXPORT void addPodcast( const KURL &url, TQListViewItem *parent = 0 );
        void loadPodcastsFromDatabase( PlaylistCategory *p = 0 );
        void registerPodcastSettings( const TQString &title, const PodcastSettings *settings );

        static bool savePlaylist( const TQString &path, const TQValueList<KURL> &urls,
                                  const TQValueList<TQString> &titles = TQValueList<TQString>(),
                                  const TQValueList<int> &lengths = TQValueList<int>(),
                                  bool relative = AmarokConfig::relativePlaylist() );

        TQString dynamicBrowserCache() const;
        TQString playlistBrowserCache() const;
        TQString podcastBrowserCache() const;
        TQString streamBrowserCache() const;
        TQString smartplaylistBrowserCache() const;

        PlaylistBrowserEntry *findItem( TQString &t, int c ) const;
        TQListViewItem *findItemInTree( const TQString &searchstring, int c ) const;
        PodcastEpisode *findPodcastEpisode( const KURL &episode, const KURL &feed ) const;

        TQPtrList<PlaylistBrowserEntry> dynamicEntries() const { return m_dynamicEntries; }
        DynamicMode *findDynamicModeByTitle( const TQString &title );
        TQListViewItem *podcastCategory() const { return m_podcastCategory; }

        static PlaylistBrowser *instance() {
            if(!s_instance)  s_instance = new PlaylistBrowser("PlaylistBrowser");
            return s_instance;
        }

        //following used by PlaylistSelection.cpp
        PlaylistBrowserView* getListView() const { return m_listview; }
        PlaylistCategory* getDynamicCategory() const { return m_dynamicCategory; }
        void saveDynamics();

    protected:
        virtual void resizeEvent( TQResizeEvent * );

    signals:
        void selectionChanged();

    public slots:
        void openPlaylist( TQListViewItem *parent = 0 );
        void scanPodcasts();

    private slots:
        void abortPodcastQueue();
        void addSelectedToPlaylist( int options = -1 );
        void collectionScanDone();
        void currentItemChanged( TQListViewItem * );
        void downloadPodcastQueue();
        void editStreamURL( StreamEntry *item, const bool readOnly=false );
        void removeSelectedItems();
        void renamePlaylist( TQListViewItem*, const TQString&, int );
        void renameSelectedItem();
        void invokeItem( TQListViewItem*, const TQPoint &, int column );
        void slotDoubleClicked( TQListViewItem *item );

        void slotAddMenu( int id );
        void slotAddPlaylistMenu( int id );
        void showContextMenu( TQListViewItem*, const TQPoint&, int );

        void loadDynamicItems();

    private:
        LIBAMAROK_EXPORT PlaylistBrowser( const char* name=0 );
        void polish();

        bool m_polished;

        PlaylistCategory* loadStreams();
        void loadCoolStreams();
        void saveStreams();

        void loadLastfmStreams( const bool subscriber = false );
        void addLastFmRadio( TQListViewItem *parent );
        void addLastFmCustomRadio( TQListViewItem *parent );
        void saveLastFm();

        PlaylistCategory* loadSmartPlaylists();
        void loadDefaultSmartPlaylists();
        void editSmartPlaylist( SmartPlaylist* );
        void saveSmartPlaylists( PlaylistCategory *smartCategory = NULL );
        void updateSmartPlaylists( TQListViewItem *root );
        void updateSmartPlaylistElement( TQDomElement& query );

        PlaylistCategory* loadDynamics();
        void fixDynamicPlaylistPath( TQListViewItem *item );
        TQString guessPathFromPlaylistName( TQString name );

        PlaylistCategory* loadPodcasts();
        TQMap<int,PlaylistCategory*> loadPodcastFolders( PlaylistCategory *p );
        void changePodcastInterval();
        void configurePodcasts( TQListViewItem *parent );
        void configurePodcasts( TQPtrList<PodcastChannel> &podcastChannelList, const TQString &caption );
        void configureSelectedPodcasts();
        bool deleteSelectedPodcastItems( const bool removeItem=false, const bool silent=false );
        bool deletePodcasts( TQPtrList<PodcastChannel> items );
        void downloadSelectedPodcasts();
        void refreshPodcasts( TQListViewItem *category );
        void removePodcastFolder( PlaylistCategory *item );
        void savePodcastFolderStates( PlaylistCategory *folder );
        PodcastChannel *findPodcastChannel( const KURL &feed, TQListViewItem *parent=0 ) const;

        void markDynamicEntries();
        PlaylistBrowserEntry* findByName( TQString name );

        PlaylistCategory* loadPlaylists();
        void savePlaylists();
        void savePlaylist( PlaylistEntry * );
        bool createPlaylist( TQListViewItem *parent = 0, bool current = true, TQString title = 0 );
        bool deletePlaylists( TQPtrList<PlaylistEntry> items );
        bool deletePlaylists( KURL::List items );

        void customEvent( TQCustomEvent* e );
        void saveM3U( PlaylistEntry *, bool append );
        void savePLS( PlaylistEntry *, bool append );
        void saveXSPF( PlaylistEntry *, bool append );

        static KURL::List recurse( const KURL &url );

        LIBAMAROK_EXPORT static PlaylistBrowser *s_instance;

        PlaylistCategory    *m_playlistCategory;
        PlaylistCategory    *m_streamsCategory;
        PlaylistCategory    *m_smartCategory;
        PlaylistCategory    *m_dynamicCategory;
        PlaylistCategory    *m_podcastCategory;
        PlaylistCategory    *m_coolStreams;
        PlaylistCategory    *m_smartDefaults;
        PlaylistCategory    *m_lastfmCategory;
        ShoutcastBrowser    *m_shoutcastCategory;
        PlaylistEntry       *m_lastPlaylist;

        DynamicEntry        *m_randomDynamic;
        DynamicEntry        *m_suggestedDynamic;

        bool                 m_coolStreamsOpen;
        bool                 m_smartDefaultsOpen;
        bool                 m_lastfmOpen;

        PlaylistBrowserView *m_listview;
        TDEActionCollection   *m_ac;
        TDEAction             *removeButton;
        TDEAction             *renameButton;
        TDEActionMenu         *viewMenuButton;
        TDEActionMenu         *addMenuButton;
        TDEToolBar            *m_toolbar;
        TQValueList<int>      m_dynamicSizeSave;

        TQDict<PodcastSettings>   m_podcastSettings;
        TQPtrList<PlaylistBrowserEntry>  m_dynamicEntries;

        TQTimer                  *m_podcastTimer;
        int                      m_podcastTimerInterval;        //in ms
        TQPtrList<PodcastChannel> m_podcastItemsToScan;
        TQPtrList<PodcastEpisode> m_podcastDownloadQueue;

        InfoPane *m_infoPane;

        bool                 m_removeDirt;

        TQSplitter *m_splitter;
};



class PlaylistBrowserView : public TDEListView
{
        TQ_OBJECT
  

    friend class PlaylistEntry;

    public:
        PlaylistBrowserView( TQWidget *parent, const char *name=0 );
        ~PlaylistBrowserView();

        void rename( TQListViewItem *item, int c );

    protected:
        virtual void keyPressEvent( TQKeyEvent * );

    private slots:
        void mousePressed( int, TQListViewItem *, const TQPoint &, int );
        void moveSelectedItems( TQListViewItem* newParent );

    private:
        void startDrag();
        void contentsDropEvent( TQDropEvent* );
        void contentsDragEnterEvent( TQDragEnterEvent* );
        void contentsDragMoveEvent( TQDragMoveEvent* );
        void contentsDragLeaveEvent( TQDragLeaveEvent* );
        void viewportPaintEvent( TQPaintEvent* );
        void eraseMarker();

        TQListViewItem   *m_marker;       //track that has the drag/drop marker under it
};

class PlaylistDialog: public KDialogBase
{
    TQ_OBJECT
  
    public:
        static TQString getSaveFileName( const TQString &suggestion = TQString(), bool proposeOverwriting = false );

    private:
        KLineEdit *edit;
        bool customChosen;
        TQString result;
        PlaylistDialog();

    private slots:
       void slotOk();

       void slotTextChanged( const TQString &s );

       void slotCustomPath();
};

// Returns true if item is Playlist, Stream, Smart Playlist or DynamicMode.
inline bool
isElement( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == ( PlaylistEntry::RTTI || StreamEntry::RTTI ||
                             SmartPlaylist::RTTI /*|| DynamicEntry::RTTI */) ? true : false;
}

inline bool
isCategory( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == PlaylistCategory::RTTI ? true : false;
}

inline bool
isDynamic( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == DynamicEntry::RTTI ? true : false;
}

inline bool
isPlaylist( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == PlaylistEntry::RTTI ? true : false;
}

inline bool
isSmartPlaylist( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == SmartPlaylist::RTTI ? true : false;
}

inline bool
isPlaylistTrackItem( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == PlaylistTrackItem::RTTI ? true : false;
}

inline bool
isPodcastChannel( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == PodcastChannel::RTTI ? true : false;
}

inline bool
isPodcastEpisode( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == PodcastEpisode::RTTI ? true : false;
}

inline bool
isStream( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == StreamEntry::RTTI ? true : false;
}

inline bool
isLastFm( TQListViewItem *item )
{
    if( !item )
        return false;
    return item->rtti() == LastFmEntry::RTTI ? true : false;
}

inline TQString
fileBaseName( const TQString &filePath )
{
    // this function returns the file name without extension
    // (e.g. if the file path is "/home/user/playlist.m3u", "playlist" is returned
    TQString fileName = filePath.right( filePath.length() - filePath.findRev( '/' ) - 1 );
    return fileName.mid( 0, fileName.findRev( '.' ) );
}

inline TQString
fileDirPath( const TQString &filePath )
{
    return filePath.left( filePath.findRev( '/' )+1 );
}



class InfoPane : public TQVBox
{
    TQ_OBJECT
  

public:
    InfoPane( TQWidget *parent );
    ~InfoPane();
    int getHeight();
    void setStoredHeight( const int newHeight );

public slots:
    void setInfo( const TQString &title, const TQString &info );

private slots:
    void toggle( bool );

private:
    HTMLView *m_infoBrowser;
    KPushButton *m_pushButton;
    bool m_enable;
    int m_storedHeight;
};


#endif
