#include "gstplayer.h"
#include <kdebug.h>
#include "songentry.h"
#include "songentryint.h"

namespace Yammi {

GstPlayer::GstPlayer(YammiModel* yammi) : MediaPlayer(yammi) {
        #ifdef ENABLE_GSTREAMER
        unsigned int maj, min, mic;
        kdDebug() << "GstPlayer::GstPlayer(YammiModel *yammi)" << endl;
        //init GStreamer to check if it works
        KDE::GST::GStreamer::init();
        KDE::GST::GStreamer::version(&maj, &min, &mic);
        kdDebug() << "GStreamer version " << maj << " " << min << " " << mic << endl;

        m_player = new KDE::GSTPlay::Play(KDE::GSTPlay::Play::PIPE_AUDIO_BUFFER_THREADED, this, "Play");

        //if not osssink, we are that here to circumvent GSTPlay's seeking bug
        if(QString::compare(yammi->config()->audioSink,"osssink")) {
            kdDebug() << yammi->config()->audioSink << endl;
            audiosink = KDE::GST::ElementFactory::make(yammi->config()->audioSink, NULL);
            if(audiosink) {
                m_player->setAudioSink(audiosink);
            } else {
                kdDebug() << yammi->config()->audioSink << " is not a valid GStreamer backend. Reverting to osssink." << endl;
            }
        }

        kdDebug() << "GstPlayer: player created, using " << yammi->config()->audioSink << " as backend" << endl;

        //this will tell us our position in our stream
        connect(m_player, SIGNAL(timeTick(long long)),SLOT(slotSetPosition(long long)));
        //this will tell us the complete length of the stream
        connect(m_player, SIGNAL(streamLength(long long)),SLOT(slotSetDuration(long long)));
        //this will tell us if the end has been reached
        connect(m_player, SIGNAL(streamEnd()), SLOT(slotDone()));
        kdDebug() << "GstPlayer: player connected" << endl;
        m_player->setState(KDE::GST::Element::STATE_NULL);
        kdDebug() << "GstPlayer: state set" << endl;
        #endif

        m_currentSong = 0;
        m_done = false;
        kdDebug() << "GstPlayer::GstPlayer(YammiModel *yammi) done!" << endl;

    }

    GstPlayer::~GstPlayer() {
        #ifdef ENABLE_GSTREAMER
        kdDebug() << "---GstPlayer::~GstPlayer(YammiModel *yammi)" << endl;
        quit( );
        delete m_player;
        //delete audiosink;
        #endif

    }


    void GstPlayer::check() {
        #ifdef ENABLE_GSTREAMER
        if(m_done) {
            if( m_currentSong == playlist->firstSong() ) {
                kdDebug() << "Song finished... get new one!" << endl;
                playlist->removeFirst( );
                m_currentSong = 0;
                emit playlistChanged( );
            }
            // if there are more songs in yammi's list, play them
            play( );
            status = getStatus();
            emit statusChanged( );

        }
        #endif

    }

    PlayerStatus GstPlayer::getStatus() {
        #ifdef ENABLE_GSTREAMER
        if( m_player->getState() == KDE::GST::Element::STATE_PLAYING )
            return PLAYING;
        if( m_player->getState() == KDE::GST::Element::STATE_PAUSED )
            return PAUSED;
        else
            // STATE_VOID_PENDING
            // STATE_NULL
            // STATE_READY
            #endif

            return STOPPED;
    }


    void GstPlayer::clearPlaylist() {
        #ifdef ENABLE_GSTREAMER
        //we don't have a playlist
        m_currentSong = 0;
        emit playlistChanged( );
        #endif

    }


    bool GstPlayer::play() {
        #ifdef ENABLE_GSTREAMER
        if( m_currentSong != 0 && getStatus() != PLAYING ) {
            m_player->setState(KDE::GST::Element::STATE_PLAYING);
            status = getStatus();
            emit statusChanged();
            return true;
        }
        #endif
        return false;
    }


    bool GstPlayer::pause() {
        #ifdef ENABLE_GSTREAMER
        if( m_currentSong != 0 && getStatus() == PLAYING ) {
            m_player->setState(KDE::GST::Element::STATE_PAUSED);
            status = getStatus();
            emit statusChanged();
            return true;
        }
        #endif
        return false;

    }


    bool GstPlayer::stop() {
        #ifdef ENABLE_GSTREAMER
        if( m_currentSong != 0 && (getStatus() == PLAYING || getStatus() == PAUSED)) {
            m_player->setState(KDE::GST::Element::STATE_READY);
            status = getStatus();
            emit statusChanged();
            return true;
        }
        #endif
        return false;
    }


    bool GstPlayer::playPause() {
        #ifdef ENABLE_GSTREAMER
        if( getStatus() == PLAYING ) {
            return pause();
        }
        #endif
        return play();
    }


    bool GstPlayer::skipForward(bool) {
        #ifdef ENABLE_GSTREAMER
        //shouldn't skip forward on the last song empty the list?
        if( playlist->count() < 2 ) {
            // there is no "next song"
            return false;
        }
        int savedStatus = getStatus();

        // stop
        if( getStatus() == PLAYING ) {
            m_player->setState(KDE::GST::Element::STATE_NULL);
        }
        m_currentSong = 0;

        // remove the first song and sync playlist again
        playlist->removeFirst( );
        syncYammi2Player();
        emit playlistChanged();

        if(!m_currentSong) {
            return false;
        }

        if(savedStatus == PLAYING) {
            play();
        }
        return true;
        #else

        return false;
        #endif

    }


    bool GstPlayer::skipBackward(bool withoutCrossfading) {
        #ifdef ENABLE_GSTREAMER
        Song* last=playlist->at(0)->song();
        // insert pseudo-song to be removed
        playlist->insert(0, new SongEntryInt(last, 0));
        #endif

        return skipForward(withoutCrossfading);
    }


    void GstPlayer::syncYammi2Player() {
        #ifdef ENABLE_GSTREAMER
        bool haveToUpdate=model->skipUnplayableSongs();

        if(playlist->count()==0) {
            if( getStatus()!=STOPPED ) {
                stop();
            }
            m_currentSong = 0;
            if(haveToUpdate) {
                emit playlistChanged();
            }
            return;
        }

        if(m_currentSong == playlist->at(0)->song()) {
            if(haveToUpdate) {
                emit playlistChanged();
            }
            return;
        }

        if (getStatus()!= STOPPED ) {
            m_player->setState(KDE::GST::Element::STATE_NULL);
        }

        m_done = false;
        QString location = model->checkAvailability( playlist->at(0)->song() );
        m_currentSong = playlist->at(0)->song();
        m_positionNs = 0;
        m_durationNs = 0;
        m_player->setLocation(location);

        if(haveToUpdate) {
            emit playlistChanged();
        }
        return;
        #endif

    }


    bool GstPlayer::jumpTo(int value) {
        #ifdef ENABLE_GSTREAMER
        if( m_currentSong == 0) {
            return false;
        }
        if( value < 0 || value > getTotalTime() ) {
            return false;
        }
        m_player->seekToTime(value * 1000000LL);

        return true;
        #else
        // just to prevent compiler warning
        value++;
        return false;
        #endif

    }


    QString GstPlayer::getCurrentFile() {
        #ifdef ENABLE_GSTREAMER
        if( m_currentSong ) {
            return model->checkAvailability( m_currentSong );
        } else {
            return "";
        }
        #else
        return "";
        #endif

    }

    void GstPlayer::slotSetPosition(long long d) {
        #ifdef ENABLE_GSTREAMER
        m_positionNs = d;
        #else
        // just to prevent compiler warning
        d++;
        #endif

    }

    int GstPlayer::getCurrentTime() {
        #ifdef ENABLE_GSTREAMER
        return m_positionNs/1000000LL;
        #else

        return 0;
        #endif

    }

    void GstPlayer::slotSetDuration(long long d) {
        #ifdef ENABLE_GSTREAMER
        m_durationNs = d;
        #else
        // just to prevent compiler warning
        d++;
        #endif

    }

    int GstPlayer::getTotalTime() {
        #ifdef ENABLE_GSTREAMER
        return m_durationNs/1000000LL;
        #else

        return 0;
        #endif

    }

    void GstPlayer::quit() {
        stop();
        m_currentSong = 0;
    }

    void GstPlayer::slotDone() {
        #ifdef ENABLE_GSTREAMER
        m_done = true;
        #endif

    }
};
