/***************************************************************************
 * copyright            : (C) 2007 Ian Monroe <ian@monroe.nu>
 *                        (C) 2008 Seb Ruiz <ruiz@kde.org>
 *                        (C) 2008 Soren Harward <stharward@gmail.com>
 *
 * 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) version 3 or any later version
 * accepted by the membership of KDE e.V. (or its successor approved
 * by the membership of KDE e.V.), which shall act as a proxy
 * defined in Section 14 of version 3 of the license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/

#ifndef AMAROK_PLAYLISTCONTROLLER_H
#define AMAROK_PLAYLISTCONTROLLER_H

#include "meta/Meta.h"
#include "meta/Playlist.h"
#include "UndoCommands.h"

#include <QObject>

class QUndoStack;

namespace Playlist
{
class Controller;
class Model;
}

namespace The
{
AMAROK_EXPORT Playlist::Controller* playlistController();
}

namespace Playlist
{
enum AddOptions
{
    Append     = 1,     /// inserts media after the last item in the playlist
    Queue      = 2,     /// inserts media after the currentTrack
    Replace    = 4,     /// clears the playlist first
    DirectPlay = 8,     /// start playback of the first item in the list
    Unique     = 16,    /// don't insert anything already in the playlist
    StartPlay  = 32,    /// start playback of the first item in the list if nothing else playing
    AppendAndPlay = Append | StartPlay,
    LoadAndPlay = Replace | StartPlay
};

class AMAROK_EXPORT Controller : public QObject
{
    Q_OBJECT

public:
    static Controller* instance();
    static void destroy();

public slots:
    void insertOptioned( Meta::TrackPtr track, int options );
    void insertOptioned( Meta::TrackList list, int options );
    void insertOptioned( Meta::PlaylistPtr playlist, int options );
    void insertOptioned( Meta::PlaylistList list, int options );
    void insertOptioned( QueryMaker *qm, int options );
    void insertOptioned( QList<KUrl>& urls, int options );

    void insertTrack( int row, Meta::TrackPtr track );
    void insertTracks( int row, Meta::TrackList list );
    void insertPlaylist( int row, Meta::PlaylistPtr playlist );
    void insertPlaylists( int row, Meta::PlaylistList playlists );
    void insertTracks( int row, QueryMaker *qm );
    void insertUrls( int row, const QList<KUrl>& urls );

    void removeRow( int row );
    void removeRows( int row, int count );
    void removeRows( QList<int>& rows );

    void moveRow( int from, int to );
    int  moveRows( QList<int>& from, int to ); // see function definition for info abt return value
    void moveRows( QList<int>& from, QList<int>& to );

    void undo();
    void redo();
    void clear();

signals:
    void canRedoChanged( bool );
    void canUndoChanged( bool );

private slots:
    void newResultReady( const QString&, const Meta::TrackList& );
    void queryDone();
    void slotFinishDirectoryLoader( const Meta::TrackList& );

private:
    Controller( QObject* parent = 0 );
    ~Controller();

    void insertionHelper( int row, Meta::TrackList& );

    Model* m_model;

    QUndoStack* m_undoStack;

    QHash<QueryMaker*, int> m_queryMap;         //! maps queries to the row where the results should be inserted
    QHash<QueryMaker*, int> m_optionedQueryMap; //! maps queries to the options to be used when inserting the result
    QHash<QueryMaker*, Meta::TrackList> m_queryMakerTrackResults;

    static Controller* s_instance;
};
}

#endif
