//
// C++ Implementation: citebasesearcher
//
// Description: 
//
//
// Author: Thach Nguyen <thach.nguyen@rmit.edu.au>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "citebasesearcher.h"

#include "searchmanager.h"
#include "bibfile.h"
#include "filters/bibprogs.h"
#include "bibentrytable.h"

#include <klocale.h>
#include <kconfig.h>
#include <kstandarddirs.h>
#include <ktempfile.h>


#include <qlabel.h>
#include <qlayout.h>
#include <qfile.h>
#include <qregexp.h>


CitebaseSearcher::CitebaseSearcher ( QObject *parent, const char *name )
		: searcher ( parent, name ),m_step ( Begin ), m_started ( false )
{
}


CitebaseSearcher::~CitebaseSearcher()
{
}

QString CitebaseSearcher::defaultName()
{
	return i18n ( "Citebase.org" );
}

QString CitebaseSearcher::source() const
{
	return m_name.isEmpty() ? defaultName() : m_name;
}


void CitebaseSearcher::readConfig ( KConfig* config_, const QString& group_ )
{
	KConfigGroupSaver groupSaver ( config_, group_ );
	QString s = config_->readEntry ( "Name", defaultName() ); 
	if ( !s.isEmpty() )
	{
		m_name = s;
	}
}

void CitebaseSearcher::saveConfig ( KConfig* config )
{

}

void CitebaseSearcher::search ( SearchKey key1, SearchKey key2, SearchKey key3 , const QString& value1, const QString& value2, const QString& value3, int operator1, int operator2 )
{
	QString str;
	QString query = QString();
	if ( !value1.isEmpty() )
	{


		switch ( key1 )
		{
			case Title:
				query = QString::fromLatin1 ( "title=" ) +value1;
				break;

			case Author:
				query = QString::fromLatin1 ( "author=" ) +value1;
				break;

			case Journal:
				query = QString::fromLatin1("publication=")+value1;
				break;
			case Year:
				query = QString::fromLatin1("yearfrom=")+value1+QString::fromLatin1("yearuntill=")+value1;
				break;
			default:
				stop();
				return;
		}
	}

	search ( query );

}

void CitebaseSearcher::stop()
{
	if ( !m_started )
	{
		return;
	}
	if ( m_job )
	{
		m_job->kill();
		m_job = 0;
	}
	m_started = false;
	m_data.truncate ( 0 );
	m_step = Begin;
	emit signalDone ( this );
}


void CitebaseSearcher::search ( QString query )
{
	m_query = query;

	m_started = true;

	if ( query.isEmpty() )
	{
		stop();
		return;
	}




	m_step = Query;
	startRequest ( QString::fromLatin1 ( "http://www.citebase.org/search?submitted=Search&%1&maxrows=10&order=DESC&type=metadata&rank=score" ).arg(m_query ) );

}

void CitebaseSearcher::slotData ( KIO::Job*, const QByteArray& data_ )
{
	QDataStream stream ( m_data, IO_WriteOnly | IO_Append );
	stream.writeRawBytes ( data_.data(), data_.size() );
}

void CitebaseSearcher::slotComplete ( KIO::Job* job_ )
{
	// since the fetch is done, don't worry about holding the job pointer
	m_job = 0;

	if ( job_->error() )
	{
		emit signalMessage ( job_->errorString(), 0 );
		stop();
		return;
	}

	if ( m_data.isEmpty() )
	{
		std::cerr << "CitebaseSearcher::slotComplete() - no data\n";
		stop();
		return;
	}

	QString str = QString::fromUtf8 ( m_data, m_data.size() );

	switch ( m_step )
	{
		case Query:
			searchResults();
			break;
		case Fetch:
			fetchResults();
			break;
		default:
			std::cerr << "CitebaseSearcher::slotComplete() - wrong step = " << m_step << "\n";
			break;
	}

}


void CitebaseSearcher::searchResults()
{

	QString str = QString::fromUtf8 ( m_data, m_data.size() );


	QRegExp rx ( QString::fromLatin1 ( ".*Showing .+ of (\\d+) found.*" ) );

	if ( !rx.exactMatch ( str ) )
	{
		signalMessage ( i18n ( "No matching records were found for your search." ), 1 );
		stop();
	}
	str = rx.cap ( 1 );
	int total = str.toInt();
	m_waitingRetrieveRange = true;
	m_step = Wait;
	if ( total > 0 )
	{
		emit signalQueryResult ( total );
	}
	else
	{
		signalMessage ( i18n ( "No matching records were found for your search." ), 1 );
		stop();
	}

}

void CitebaseSearcher::fetchResults()
{
	KTempFile tmpfile;
	tmpfile.setAutoDelete(true);
    	QString fn = tmpfile.name();
	QFile f ( fn );
	if ( f.open ( IO_WriteOnly ) )
	{
		QTextStream t ( &f );
		t << QString::fromUtf8 ( m_data, m_data.size() );
	}
	f.close();
	//Read bibfile
	BibentryTable *entryList = new BibentryTable();
	entryList->readBibfile ( const_cast<char*>(fn.ascii()), false );
	int total;
	if (m_total < entryList->size())
		total = m_total;
	else
		total = entryList->size();	

	for ( int i = 0; i < total; i++ )
	{
		BibEntry *bib = entryList->get_entry ( i );
		if ( bib )
			emit signalResultFound ( new BibEntry ( *bib ) );
	}
	delete entryList;
	stop();

}


void CitebaseSearcher::retrieveRange ( unsigned int min, unsigned int max )
{
	if ( m_step != Wait )
		return;
	m_waitingRetrieveRange = false;
	if ( min < 1 && max < 1 )
	{
		stop();
		return;
	}

	m_step = Fetch;
	int total;
	m_total = max-min+1;
	if (m_total < 10)
		total = 10;
	else
		total = m_total;
	QString url = QString ( "http://www.citebase.org/search?submitted=Search&%1&maxrows=%2&pos=%3&format=BibTeX&order=DESC&type=metadata&rank=score" ).arg ( m_query ).arg ( total ).arg ( min-1 );
	startRequest ( url );
}


void CitebaseSearcher::startRequest ( QString url )
{
	m_data.truncate ( 0 );
	m_url = KURL ( url );

//	std::cerr << m_url.prettyURL() << "\n";
	m_job = KIO::get ( m_url, false, false );

	connect ( m_job, SIGNAL ( data ( KIO::Job*, const QByteArray& ) ),
	          SLOT ( slotData ( KIO::Job*, const QByteArray& ) ) );
	connect ( m_job, SIGNAL ( result ( KIO::Job* ) ),
	          SLOT ( slotComplete ( KIO::Job* ) ) );



}

void CitebaseSearcher::setSource ( const QString s )
{
	m_name = s ;
}


QStringList CitebaseSearcher::searchKey()
{
	QStringList keyList;
	keyList << searchManager::self()->searchKeyString ( Author )
	<< searchManager::self()->searchKeyString ( Title ) << searchManager::self()->searchKeyString ( Journal )
	<< searchManager::self()->searchKeyString ( Year );
	return keyList;
}

SearcherConfigWidget* CitebaseSearcher::configWidget ( QWidget* parent_ )
{
	return new CitebaseConfigWidget ( parent_, this );
}

CitebaseConfigWidget::CitebaseConfigWidget ( QWidget* parent_, CitebaseSearcher* searcher_/*=0*/ )
		: SearcherConfigWidget ( parent_ )
{
	m_searcher = searcher_;
	QVBoxLayout* l = new QVBoxLayout ( optionsWidget() );
	l->addWidget ( new QLabel ( i18n ( "This source has no options." ), optionsWidget() ) );
	KURLLabel *urlLab = new KURLLabel( optionsWidget() );
	l->addWidget(urlLab);
	urlLab->setText( "More information about Citebase");
        urlLab->setURL("http://www.citebase.org");
    
	connect(urlLab , SIGNAL( leftClickedURL( const QString& ) ), kapp, SLOT( invokeBrowser( const QString& ) ) );
	l->addStretch();
}

#include "citebasesearcher.moc"
