
#include "bugdetailsjob.h"
#include "bug.h"
#include "bugdetails.h"
#include "bugdetailsimpl.h"
#include "packageimpl.h"
#include "nodefilter.h"

#include <dom/dom_element.h>
#include <dom/html_inline.h>
#include <dom/dom_text.h>
#include <qregexp.h>

#include <kdebug.h>
#include <assert.h>

BugDetailsJob::BugDetailsJob()
{
}

BugDetailsJob::~BugDetailsJob()
{
}

void BugDetailsJob::start( const Bug &bug )
{
    m_bug = bug;

    QString bugNumber = bug.number();
    QString bugUrl = "http://bugs.kde.org/db/" + bugNumber.left(2) + "/" +
                     bugNumber + ".html";

    kdDebug() << "BugDetailsJob::start(): " << bugUrl << endl;
    HTMLBugJob::start( KURL( bugUrl ) );
}

void BugDetailsJob::process()
{
    m_parts.clear();

    QStringList tags;
    tags << "pre" << "tt" << "h2" << "font";
    processFiltered( tags );

    QString text = m_parts[0].text;

    parseAttribute( text, "Package" );
    parseAttribute( text, "Severity" );
    QString version = parseAttribute( text, "Version:" );
    QString source = parseAttribute( text, "Installed from:" );
    QString compiler = parseAttribute( text, "Compiler:" );
    parseAttribute( text, "OS/Compiler notes:" );
    QString os = parseAttribute( text, "OS:" );

    m_parts[0].text = text.stripWhiteSpace();

    m_bugDetails = BugDetails( new BugDetailsImpl( version, source, compiler, os,
                                                   m_parts ) );

    emit bugDetailsAvailable( m_bug, m_bugDetails );
}


void BugDetailsJob::processNode( const DOM::Node &n )
{
    DOM::Element e = n;

    //kdDebug() << "BugDetailsJob::processNode(): " << e.tagName().string() << endl;

    DOM::DOMString tagName = e.tagName();
    if ( tagName == "pre" || tagName == "tt" ) {
        QString text;
#if 0
        for ( DOM::Node i = e.firstChild(); !i.isNull(); i = i.nextSibling() ) {
            kdDebug() << "  NodeType: " << i.nodeType() << endl;
            if ( i.nodeType() == DOM::Node::TEXT_NODE ) {
                DOM::Text textElement = i;
                text.append( textElement.data().string() );
            } else if ( i.nodeType() == DOM::Node::ELEMENT_NODE ) {
                DOM::Element quoteElement = i.firstChild();
                DOM::Text textElement = quoteElement.firstChild();
                text.append("<i><font color=#191970>" + textElement.data().string() + "</font></i>" );
            }
        }
#endif
        // toHTML does it all for us, and it also escapes entities
        text = e.toHTML();

        // Bug reporters don't wrap at 80... let's do it ourselves then
        QStringList lines = QStringList::split( '\n', text );
        for ( QStringList::Iterator it = lines.begin() ; it != lines.end() ; ++it )
        {
            QString line = *it;
            QString wrappedLine;
            while ( line.length() > 80 )
            {
                int breakPoint = line.findRev( ' ', 80 );
                if( breakPoint == -1 ) {
                    wrappedLine += line.left( 80 ) + '\n';
                    line = line.mid( 80 );
                } else {
                    wrappedLine += line.left( breakPoint ) + '\n';
                    line = line.mid( breakPoint + 1 );
                }
            }
            wrappedLine += line; // the remainder
            (*it) = wrappedLine;
        }
        text = lines.join( "\n" );

        //kdDebug() << "BugDetailsJob::processNode created part with text=" << text << endl;
        m_parts.prepend( BugDetailsPart( Person::parseFromString( mSender ), mDate, text ) );
    } else if ( e.tagName() == "h2" ) {
        DOM::Text textElement = e.firstChild();
        //kdDebug() << "--- h2 text: " << textElement.data().string() << endl;

        mSender = QString::null;
        mDate = QString::null;

        for ( DOM::Node i = n; !i.isNull(); i = i.nextSibling() ) {
//            kdDebug() << "  NodeType: " << i.nodeType() << endl;
            if ( i.nodeType() == DOM::Node::TEXT_NODE ) {
                DOM::Text textElement = i;
                QString fieldName = textElement.data().string();
                if ( fieldName.startsWith( " From:" ) ) {
                    DOM::Text senderElement = i.nextSibling().firstChild();
                    mSender = senderElement.data().string();
                }
                if ( fieldName.startsWith( " Date:" ) ) {
                    mDate = fieldName.mid(7);
                }
            }
            if ( !mSender.isNull() && !mDate.isNull() ) break;
        }

#if 0
        kdDebug() << "  Sender: " << mSender << endl;
        kdDebug() << "  Date: " << mDate << endl;

        DOM::Text textElement = e.firstChild();
        kdDebug() << "--- h2 text: " << textElement.data().string() << endl;
        textElement = e.nextSibling();
        kdDebug() << "--- header: " << textElement.data().string() << endl;
        DOM::Node senderNode = e.nextSibling();
        textElement = senderNode.firstChild();
        kdDebug() << "--- sender: " << textElement.data().string() << endl;
#endif
    }
}

QString BugDetailsJob::parseAttribute( QString &text, const QString &attr )
{
    QString result;
    int posBegin = text.find( attr );
    if ( posBegin > 0 ) {
        int posBegin2 = posBegin + attr.length();
        int posEnd = text.find( "<br />", posBegin2 );
        if ( posEnd > 0 ) {
            result = text.mid( posBegin2 + 1, posEnd - posBegin2 - 1 );
            result = result.stripWhiteSpace();
	    // Don't forget to substract length of <br /> tag.
            text.replace( posBegin, posEnd - posBegin + 7, "" );
        }
    }
    return result;
}

#include "bugdetailsjob.moc"

/*
 * vim:sw=4:ts=4:et
 */
