/***************************************************************************
 *   Copyright (C) 2004-2006 by Pere Constans
 *   constans@molspaces.com
 *   cb2Bib version 0.6.1
 *   See LICENSE file that comes with this distribution
 ***************************************************************************/
#include "c2bnetworkquery.h"
#include "c2bnetwork.h"
#include "c2butils.h"
#include "cb2bib_par.h"

#include <qdir.h>
#include <qmessagebox.h>
#include <qregexp.h>
#include <qsettings.h>
#include <qurl.h>
#include <qwidget.h>


c2bNetworkQuery::c2bNetworkQuery(c2bNetwork* n, QObject *parent, const char *name)
        : QObject(parent, name)
{
    net = n;
    pWidget = (QWidget*) parent;
    Queryfile1 = QDir::homeDirPath() + QDir::separator() + "cb2bib_query_tmp_html1";
    Queryfile2 = QDir::homeDirPath() + QDir::separator() + "cb2bib_query_tmp_html2";
    readSettings();
}

c2bNetworkQuery::~c2bNetworkQuery()
{}


void c2bNetworkQuery::submitQ( const QString& jn, const QString& vol, const QString& fp )
{
    // Submission Initialization
    error = "";
    m_q_number = 0;
    m_endoffile = FALSE;
    JournalN = jn;
    Volume = vol;
    FPage = fp;
    submitQ1();
}

void c2bNetworkQuery::submitQ1()
{
    // Submission, first step, setting journal codes

    if ( !setQueryParams( JournalN ) )
    {
        error = tr("No info for querying journal '%1'").arg(JournalN);
        emit queryEnded( FALSE, targetQ, Queryfile1 );
        return;
    }

    if ( m_endoffile )
    {
        error = tr("Performed %1 queries: No article found.").arg(m_q_number);
        emit queryEnded( FALSE, targetQ, Queryfile1 );
        return;
    }

    c2bDebug(QString("Query Number = %1").arg(m_q_number));
    c2bDebug(QString("targetQ[%1]").arg(targetQ));
    c2bDebug(QString("captionQ[%1]").arg(captionQ));
    c2bDebug(QString("referenceurl_prefix[%1]").arg(referenceurl_prefix));
    c2bDebug(QString("referenceurl_sufix[%1]").arg(referenceurl_sufix));
    c2bDebug(QString("pdfurl_prefix[%1]").arg(pdfurl_prefix));
    c2bDebug(QString("pdfurl_sufix[%1]").arg(pdfurl_sufix));
    c2bDebug(QString("action[%1]").arg(action));
    c2bDebug(QString("POST1[%1]").arg(targetQ));

    if ( action == "browse_query" )
    {
        net->openFile( targetQ );
        error = "Browsing query.";
        emit queryEnded( TRUE, "", "" );
        return;
    }
    emit message( tr("Query: %1").arg(targetQ) );
    net->getFile( targetQ, Queryfile1, "copy", this, SLOT(submitQ2(bool)) );
}

void c2bNetworkQuery::submitQ2( bool stat )
{
    // Submission, second part: extracting reference location

    if ( !stat )
    {
        error = net->getErrorString();
        emit queryEnded( FALSE, targetQ, Queryfile1 );
        return;
    }

    QString lines = "";
    QFile file( Queryfile1 );
    if ( file.open( IO_ReadOnly ) )
    {
        QTextStream stream( &file );
        while ( !stream.atEnd() )
            lines += stream.readLine()+"\n";
        if ( !m_keeptmp )
            file.remove();
    }

    QRegExp rx ( captionQ );
    rx.setMinimal( TRUE );
    if ( ! rx.isValid() )
        qDebug( QString("cb2Bib: RegExp |%1| is not valid.").arg(captionQ) );
    int ncap = rx.search( lines );
    if( ncap > -1 )
        lines = rx.cap( 1 );
    else
    {
        submitQ1();
        return;
    }
    targetBib = referenceurl_prefix + lines + referenceurl_sufix;
    if ( pdfurl_prefix.isEmpty() && pdfurl_sufix.isEmpty() )
        targetPDF = "";
    else if( m_autopdf )
        targetPDF = pdfurl_prefix + lines + pdfurl_sufix;

    c2bDebug(QString("CAPTURED[%1]").arg(lines));
    c2bDebug(QString("POST2[%1]").arg(targetBib));
    c2bDebug(QString("POST3[%1]").arg(targetPDF));

    if ( action == "browse_referenceurl" )
    {
        net->openFile( targetBib );
        error = "Browsing reference.";
        emit queryEnded( TRUE, "", "" );
        return;
    }
    emit message( tr("Retrieving: %1").arg(targetBib) );
    net->getFile( targetBib, Queryfile2, "copy", this, SLOT(QueryDone(bool)) );
}

void c2bNetworkQuery::QueryDone( bool stat )
{
    // Submission Done

    if ( !stat )
    {
        error = net->getErrorString();
        emit queryEnded( FALSE, targetBib, Queryfile2 );
        return;
    }

    QString lines = "";
    QFile file( Queryfile2 );
    if ( file.open( IO_ReadOnly ) )
    {
        QTextStream stream( &file );
        while ( !stream.atEnd() )
            lines += stream.readLine()+"\n";
        if ( !m_keeptmp )
            file.remove();
    }
    if ( targetBib.contains( "MEDLINE" ) )
        lines.replace( QRegExp("^.+<pre>(.+)</pre>.+$"), "\\1" );
    targetBib = lines.stripWhiteSpace();
    emit queryEnded( TRUE, targetPDF, targetBib );
}

const QString c2bNetworkQuery::errorString()
{
    return error;
}

void c2bNetworkQuery::readSettings()
{
    QSettings settings;
    settings.insertSearchPath( QSettings::Windows, WINDOWS_REGISTRY );
    m_autopdf = settings.readBoolEntry( APP_KEY + "autopdfd", APP_AUTO_PDFD );
    m_keeptmp = settings.readBoolEntry( APP_KEY + "keeptmpf", APP_KEEP_TMPF );
    m_netqinffl = QDir::convertSeparators(settings.readEntry( APP_KEY + "netqinffl", APP_NETQIF ));
}

const QString c2bNetworkQuery::bookMarks()
{
    if ( m_netqinffl.isEmpty() )
        return "";
    QFile file( m_netqinffl );
    if ( ! file.open( IO_ReadOnly ) )
        return "";
    m_bookmarks = "<p align=\"center\">Bookmarks:<br /><p align=\"center\"><em>";
    bool bm_found = FALSE;
    QRegExp rx("bookmark=");
    QString line;
    QTextStream stream( &file );
    while ( !stream.atEnd() )
    {
        line = stream.readLine();
        if ( !( line.isEmpty() || line.contains(QRegExp("^#")) ) )
        {
            if ( line.contains( rx ) )
            {
                bm_found = TRUE;
                line.replace( rx, "" );
                QStringList spLine = QStringList::split( "|", line );
                QString url = QString("<a href=\"%1\">%2</a>").arg(spLine[1]).arg(spLine[0]);
                m_bookmarks += QString("%1 <br />").arg(url);
            }
        }
    }
    file.close();
    if ( !bm_found )
        return "";
    m_bookmarks += "</em></p><br />";
    return m_bookmarks;
}

bool c2bNetworkQuery::setQueryParams( const QString& jn )
{
    if ( m_netqinffl.isEmpty() )
    {
        QMessageBox::information( pWidget, tr("cb2Bib Info"),
                                  tr( QString("No Network Query Info filename specified.\n\n") ) +
                                  tr( "Usue cb2Bib Configure button to choose a filename and location.\n\n" ), tr("&Continue") );
        return FALSE;
    }
    QFile file( m_netqinffl );
    if ( ! file.open( IO_ReadOnly ) )
    {
        QMessageBox::warning( pWidget, tr("cb2Bib Info"),
                              tr( QString("Unable to open Network Query Info file %1 for reading.\nError: '%2'\n\n").
                                  arg(m_netqinffl).arg(file.errorString()) ) +
                              QString("Usue the Configure button to choose filename and location.\n\n"), tr("&Continue") );
        return FALSE;
    }

    QString line;
    QTextStream stream( &file );
    QRegExp rx("journal="+jn+"\\|");
    QRegExp rxany("journal=\\s*$");
    uint readQueryParams = 0;
    m_endoffile = FALSE;
    while ( !stream.atEnd() )
    {
        line = stream.readLine();
        if ( !( line.isEmpty() || line.contains(QRegExp("^#")) ) )
        {
            if ( line.contains( rx ) )
            {
                QStringList spLine = QStringList::split( "|", line );
                jcode = spLine[1];
            }
            else if ( line.contains( rxany ) )
                jcode = jn;
            if ( line.contains( rx ) || line.contains( rxany ) )
            {
                if ( readQueryParams++ == m_q_number )
                {
                    while ( line.contains( QRegExp("^journal=") ) )
                        line = stream.readLine();
                    targetQ = line.replace( QRegExp("^query="), "" );
                    line = stream.readLine();
                    captionQ = line.replace( QRegExp("^capture_from_query="), "" );
                    line = stream.readLine();
                    referenceurl_prefix = line.replace( QRegExp("^referenceurl_prefix="), "" );
                    line = stream.readLine();
                    referenceurl_sufix = line.replace( QRegExp("^referenceurl_sufix="), "" );
                    line = stream.readLine();
                    pdfurl_prefix = line.replace( QRegExp("^pdfurl_prefix="), "" );
                    line = stream.readLine();
                    pdfurl_sufix = line.replace( QRegExp("^pdfurl_sufix="), "" );
                    line = stream.readLine();
                    action = line.replace( QRegExp("^action="), "" );
                    // Setting Query Parameters
                    QUrl::encode( jcode );
                    targetQ.replace( "<<journal>>", jcode );
                    captionQ.replace( "<<journal>>", jcode );
                    referenceurl_prefix.replace( "<<journal>>", jcode );
                    referenceurl_sufix.replace( "<<journal>>", jcode );
                    pdfurl_prefix.replace( "<<journal>>", jcode );
                    pdfurl_sufix.replace( "<<journal>>", jcode );
                    targetQ.replace( "<<pages>>", FPage );
                    captionQ.replace( "<<pages>>", FPage );
                    referenceurl_prefix.replace( "<<pages>>", FPage );
                    referenceurl_sufix.replace( "<<pages>>", FPage );
                    pdfurl_prefix.replace( "<<pages>>", FPage );
                    pdfurl_sufix.replace( "<<pages>>", FPage );
                    targetQ.replace( "<<volume>>", Volume );
                    captionQ.replace( "<<volume>>", Volume );
                    referenceurl_prefix.replace( "<<volume>>", Volume );
                    referenceurl_sufix.replace( "<<volume>>", Volume );
                    pdfurl_prefix.replace( "<<volume>>", Volume );
                    pdfurl_sufix.replace( "<<volume>>", Volume );
                    m_q_number++;
                    return TRUE;
                }
            }
        }
    }
    file.close();
    m_endoffile = TRUE;
    return (m_q_number > 0);
}
