#include "playlist.h"
#include "playlistitem.h"

#include <SWidgetList>
#include <SMasterIcons>

#include <QUrl>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileInfo>
#include <QDropEvent>
#include <QDir>
#include <QPushButton>
#include <QPainter>
#include <QPaintEvent>
#include <QDebug>

#include <tag.h>
#include <fileref.h>

class PlayListPrivate
{
public:
    QStringList list;
    SWidgetList *widget_list;
    QVBoxLayout *layout;

    PlayListItem *current;
    PlayListItem *selected;

    PlayList::RepeatStatus repeat;

    QPushButton *clear_list_btn;
    QPushButton *shuffle_btn;
    QPushButton *repeat_btn;

    QHBoxLayout *buttons_layout;
};

PlayList::PlayList(QWidget *parent) :
    QFrame(parent)
{
    setAcceptDrops( true );

    p = new PlayListPrivate;
    p->current = 0;
    p->repeat  = PlayList::List;

    p->widget_list = new SWidgetList();
        p->widget_list->setFrameShadow( QFrame::Plain );
        p->widget_list->setFrameShape( QFrame::NoFrame );

    p->clear_list_btn = new QPushButton();
        p->clear_list_btn->setText( tr("Clear") );
        p->clear_list_btn->setIcon( SMasterIcons::icon(QSize(48,48),"edit-clear.png") );
        p->clear_list_btn->setFlat( true );
        p->clear_list_btn->setSizePolicy( QSizePolicy::Expanding , QSizePolicy::Fixed );

    p->shuffle_btn = new QPushButton();
        p->shuffle_btn->setText( tr("Shuffle") );
        p->shuffle_btn->setIcon( SMasterIcons::icon(QSize(48,48),"roll.png") );
        p->shuffle_btn->setFlat( true );
        p->shuffle_btn->setSizePolicy( QSizePolicy::Expanding , QSizePolicy::Fixed );

    p->repeat_btn = new QPushButton();
        p->repeat_btn->setText( tr("Repeat") );
        p->repeat_btn->setIcon( SMasterIcons::icon(QSize(48,48),"format-list-unordered.png") );
        p->repeat_btn->setFlat( true );
        p->repeat_btn->setSizePolicy( QSizePolicy::Expanding , QSizePolicy::Fixed );

    p->buttons_layout = new QHBoxLayout();
        p->buttons_layout->addWidget( p->clear_list_btn );
        p->buttons_layout->addWidget( p->repeat_btn );
        p->buttons_layout->addWidget( p->shuffle_btn );

    p->layout = new QVBoxLayout( this );
        p->layout->setContentsMargins( 0 , 0 , 0 , 0 );
        p->layout->addWidget( p->widget_list );
        p->layout->addLayout( p->buttons_layout );

    connect( p->widget_list , SIGNAL(doubleClicked(QWidget*)) , SLOT(itemDoubleClicked(QWidget*)) );

    connect( p->clear_list_btn , SIGNAL(clicked()) , SLOT(clear()) );

    setFrameShadow( QFrame::Sunken );
    setFrameShape( QFrame::StyledPanel );
}

void PlayList::addFolder( const QString & path )
{
    const QStringList & files = QDir(path).entryList( QDir::Files );
    for( int i=0 ; i<files.count() ; i++ )
        addFile( path + "/" + files.at(i) );

    const QStringList & dirs = QDir(path).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
    for( int i=0 ; i<dirs.count() ; i++ )
        addFolder( path + "/" + dirs.at(i) );
}

void PlayList::addFiles( const QStringList & files )
{
    for( int i=0 ; i<files.count() ; i++ )
        addFile( files.at(i) );
}

void PlayList::addFile( const QString & file )
{
    TagLib::FileRef file_ref( file.toUtf8().constData() );
    TagLib::Tag    *tag = file_ref.tag();
    if( !tag )
        return ;

    PlayListItem *item = new PlayListItem();
        item->set( file , QString::fromUtf8(tag->title().to8Bit(true).c_str()) , QString() );

    p->widget_list->addWidget( item );
    p->list << file;
}

void PlayList::addFilesAndPlay( const QStringList & files )
{
    if( files.isEmpty() )
        return;

    for( int i=0 ; i<files.count() ; i++ )
        addFile( files.at(i) );

    play( files.first() );
}

void PlayList::addFileAndPlay( const QString & file )
{
    addFile( file );
    play( file );
}

const QStringList *PlayList::list() const
{
    return &p->list;
}

void PlayList::clear()
{
    p->current = 0;
    while( !p->widget_list->isEmpty() )
    {
        QWidget *w = p->widget_list->widget( 0 );
            p->widget_list->removeAt( 0 );
            p->list.removeAt( 0 );

        delete w;
    }
}

void PlayList::play( const QString & address )
{
    for( int i=0 ; i<p->widget_list->count() ; i++ )
        if( static_cast<PlayListItem*>(p->widget_list->widget(i))->address() == address )
        {
            p->widget_list->doubleClick( i );
            break;
        }
}

void PlayList::next()
{
    if( p->current == 0 )
        return ;

    int index = p->widget_list->indexOf(p->current) + 1;
    if( index == p->widget_list->count() )
    {
        switch( static_cast<int>(p->repeat) )
        {
        case PlayList::List :
            index = 0;
            break;

        case PlayList::Track :
            index--;
            break;

        case PlayList::Off :
            return;
            break;
        }
    }

    p->current->setState( PlayListItem::Stopped );
    p->current = static_cast<PlayListItem*>( p->widget_list->widget(index) );
    playCurrent();
}

void PlayList::previous()
{
    if( p->current == 0 )
        return ;

    int index = p->widget_list->indexOf(p->current) - 1;
    if( index == -1 )
    {
        switch( static_cast<int>(p->repeat) )
        {
        case PlayList::List :
            index = p->widget_list->count()-1;
            break;

        case PlayList::Track :
            index++;
            break;

        case PlayList::Off :
            return;
            break;
        }
    }

    p->current->setState( PlayListItem::Stopped );
    p->current = static_cast<PlayListItem*>( p->widget_list->widget(index) );
    playCurrent();
}

void PlayList::playCurrent()
{
    if( p->current == 0 )
        return ;

    p->widget_list->setSelected( QList<QWidget*>()<< p->current );

    p->current->setState( PlayListItem::Play );
    emit playing( p->current->address() );
}

void PlayList::itemDoubleClicked( QWidget *widget )
{
    if( p->current != 0 )
        p->current->setState( PlayListItem::Stopped );

    p->current = static_cast<PlayListItem*>( widget );
    playCurrent();
}

void PlayList::itemClicked( QWidget *widget )
{
    p->selected = static_cast<PlayListItem*>( widget );
}

void PlayList::paintEvent( QPaintEvent *event )
{
    QRect rct;
        rct.setX( frameWidth() );
        rct.setY( frameWidth() );
        rct.setWidth( rect().width() - 2*frameWidth() );
        rct.setHeight( rect().height() - 2*frameWidth() );

    QPainter painter( this );
        painter.fillRect( rct , palette().base() );

    QFrame::paintEvent( event );
}

void PlayList::dropEvent( QDropEvent *event )
{
    QList<QUrl> list = event->mimeData()->urls();

    for( int i=0 ; i< list.count() ; i++ )
    {
        QString url_path = list.at(i).path();

#ifdef Q_OS_WIN32
        if( url_path[0] == '/' )
            url_path.remove( 0 , 1 );
#endif

        QFileInfo file( url_path );
        if( file.isDir() )
            addFolder( url_path );
        else
            addFile( url_path );
    }

    event->acceptProposedAction();
    QWidget::dropEvent( event );
}

void PlayList::dragEnterEvent( QDragEnterEvent *event )
{
    if( event->mimeData()->hasUrls() )
        event->acceptProposedAction();

    QWidget::dragEnterEvent( event );
}

PlayList::~PlayList()
{
    delete p;
}
