/***************************************************************************
 *   Copyright (c) 2008  Nikolaj Hald Nielsen <nhnFreespirit@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) any later version.                                   *
 *                                                                         *
 *   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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.          *
 ***************************************************************************/

#include "OpmlDirectoryXmlParser.h"

#include "Amarok.h"
#include "Debug.h"
#include "statusbar/StatusBar.h"

#include <QDomDocument>
#include <QFile>

#include <KLocale>
#include <threadweaver/Job.h>

using namespace Meta;

OpmlDirectoryXmlParser::OpmlDirectoryXmlParser( const QString &filename )
        : ThreadWeaver::Job()
        , n_numberOfTransactions ( 0 )
        , n_maxNumberOfTransactions ( 5000 )
{
    DEBUG_BLOCK
    m_sFileName = filename;
    albumTags.clear();
    m_dbHandler = new OpmlDirectoryDatabaseHandler();
    m_currentCategoryId = -1;
    connect( this, SIGNAL( done( ThreadWeaver::Job* ) ), SLOT( completeJob() ) );
}

OpmlDirectoryXmlParser::~OpmlDirectoryXmlParser()
{
    DEBUG_BLOCK
    delete m_dbHandler;
}

void
OpmlDirectoryXmlParser::run()
{
    readConfigFile( m_sFileName );
}

void
OpmlDirectoryXmlParser::completeJob( )
{
    The::statusBar()->longMessage(
        i18n( "OpmlDirectory update complete. Added %1 feeds in %2 categories", m_nNumberOfFeeds, m_nNumberOfCategories ),
        StatusBar::Information );


    debug() << "OpmlDirectoryXmlParser: total number of albums: " << m_nNumberOfCategories;
    debug() << "OpmlDirectoryXmlParser: total number of tracks: " << m_nNumberOfFeeds;
    emit doneParsing();
    deleteLater();
}

void
OpmlDirectoryXmlParser::readConfigFile( const QString &filename )
{
    DEBUG_BLOCK
    m_nNumberOfFeeds = 0;
    m_nNumberOfCategories = 0;

    QDomDocument doc( "opml" );

    if ( !QFile::exists( filename ) )
    {
        debug() << "Opml file does not exist";
        return;
    }

    QFile file( filename );
    if ( !file.open( QIODevice::ReadOnly ) ) {
        debug() << "OpmlDirectoryXmlParser::readConfigFile error reading file";
        return ;
    }
    if ( !doc.setContent( &file ) )
    {
        debug() << "OpmlDirectoryXmlParser::readConfigFile error parsing file";
        file.close();
        return ;
    }
    file.close();

    QFile::remove( filename );

    m_dbHandler->destroyDatabase();
    m_dbHandler->createDatabase();

    //run through all the elements
    QDomElement docElem = doc.documentElement();

    m_dbHandler->begin(); //start transaction (MAJOR speedup!!)
    debug() << "begin parsing content";
    parseElement( docElem );
    debug() << "finishing transaction";
    m_dbHandler->commit(); //complete transaction

    //completeJob is called by ThreadManager
}

void
OpmlDirectoryXmlParser::parseElement( const  QDomElement &e )
{
    QString sElementName = e.tagName();

    if( sElementName == "outline" )
    {
        if ( e.hasChildNodes() )
            parseCategory( e );
        else
            parseFeed( e );
    }
    else
        parseChildren( e );
}

void
OpmlDirectoryXmlParser::parseChildren( const  QDomElement &e )
{
    QDomNode n = e.firstChild();

    while ( !n.isNull() )
    {
        if ( n.isElement() )
            parseElement( n.toElement() );

        n = n.nextSibling();
    }
}


void OpmlDirectoryXmlParser::parseCategory( const  QDomElement &e)
{
    m_nNumberOfCategories++;

    QString name = e.attribute( "text", "Unknown" );
    ServiceAlbumPtr currentCategory = ServiceAlbumPtr( new OpmlDirectoryCategory( name ) );

    m_currentCategoryId = m_dbHandler->insertAlbum( currentCategory );
    countTransaction();

    parseChildren( e );
}

void OpmlDirectoryXmlParser::parseFeed( const QDomElement &e )
{
    m_nNumberOfFeeds++;

    QString name = e.attribute( "text", "Unknown" );
    QString url = e.attribute( "url", "" );

    OpmlDirectoryFeedPtr currentFeed = OpmlDirectoryFeedPtr( new OpmlDirectoryFeed( name ) );
    currentFeed->setAlbumId( m_currentCategoryId );
    currentFeed->setUidUrl( url );

    m_dbHandler->insertTrack( ServiceTrackPtr::dynamicCast( currentFeed ) );
    
    countTransaction();
}


void OpmlDirectoryXmlParser::countTransaction()
{
    n_numberOfTransactions++;
    if ( n_numberOfTransactions >= n_maxNumberOfTransactions )
    {
        m_dbHandler->commit();
        m_dbHandler->begin();
        n_numberOfTransactions = 0;
    }
}

#include "OpmlDirectoryXmlParser.moc"

