/* This file is part of Clementine.
   Copyright 2010, David Sansome <me@davidsansome.com>

   Clementine 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 3 of the License, or
   (at your option) any later version.

   Clementine 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 Clementine.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef SONGLOADER_H
#define SONGLOADER_H

#include <QObject>
#include <QUrl>

#include "song.h"

#include <boost/shared_ptr.hpp>

#include <gst/gst.h>

class CueParser;
class LibraryBackendInterface;
class ParserBase;
class PlaylistParser;

class SongLoader : public QObject {
  Q_OBJECT
public:
  SongLoader(LibraryBackendInterface* library, QObject* parent = 0);
  ~SongLoader();

  enum Result {
    Success,
    Error,
    WillLoadAsync,
  };

  static const int kDefaultTimeout;

  const QUrl& url() const { return url_; }
  const SongList& songs() const { return songs_; }

  int timeout() const { return timeout_; }
  void set_timeout(int msec) { timeout_ = msec; }

  Result Load(const QUrl& url);

signals:
  void LoadFinished(bool success);

private slots:
  void Timeout();
  void StopTypefind();

private:
  enum State {
    WaitingForType,
    WaitingForMagic,
    WaitingForData,
    Finished,
  };

  Result LoadLocal(const QString& filename, bool block = false, bool ignore_playlists = false);
  void LoadLocalDirectory(const QString& filename);
  void LoadPlaylist(ParserBase* parser, const QString& filename);
  void LoadLocalDirectoryAndEmit(const QString& filename);
  void LoadPlaylistAndEmit(ParserBase* parser, const QString& filename);

  void AddAsRawStream();

  Result LoadRemote();

  // GStreamer callbacks
  static void TypeFound(GstElement* typefind, uint probability, GstCaps* caps, void* self);
  static void DataReady(GstPad*, GstBuffer* buf, void* self);
  static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage*, gpointer);
  static gboolean BusCallback(GstBus*, GstMessage*, gpointer);

  void StopTypefindAsync(bool success);
  void ErrorMessageReceived(GstMessage* msg);
  void EndOfStreamReached();
  void MagicReady();

private:
  static QSet<QString> sRawUriSchemes;

  QUrl url_;
  SongList songs_;

  QTimer* timeout_timer_;
  PlaylistParser* playlist_parser_;
  CueParser* cue_parser_;

  // For async loads
  int timeout_;
  State state_;
  bool success_;
  ParserBase* parser_;
  QString mime_type_;
  QByteArray buffer_;
  LibraryBackendInterface* library_;

  boost::shared_ptr<GstElement> pipeline_;
};

#endif // SONGLOADER_H
