/***************************************************************************
 *   Copyright (C) 2005 by xavier helluy   *
 *   xavier.helluy@web.de   *
 *                                                                         *
 *   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 Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/
 
 
#include <kdebug.h>
#include <kglobalsettings.h>
#include <kstandarddirs.h>
#include <kdesktopfile.h>
#include <kservice.h>
#include <klocale.h>

#include <qdir.h>
#include <qfile.h>

#include <sys/stat.h>
#include <kio/slavebase.h>
#include <qstringlist.h>

#include <kwest_search_daemon_dcopiface_stub.h>

#include <kuser.h>
#include <qfile.h>

#include <qcstring.h>
#include <qsocket.h>
#include <qdatetime.h>
#include <qbitarray.h>

#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include <kmessagebox.h>
//#include <kinstance.h
#include <kglobal.h>
#include <kstandarddirs.h>
#include <klocale.h>
#include <kurl.h>
#include <ksock.h>
#include <kconfig.h>
#include <dcopclient.h>
#include <kapplication.h>

#include <stdlib.h>
#include "kwestdcoprequest.h"

#include <unistd.h> // //02.06.05 Jol  sleep or QThread::sleep (protected) 

KwestDCOPRequest::KwestDCOPRequest(QString query) 
	: QObject() , m_query(query)
{
}


KwestDCOPRequest::~KwestDCOPRequest()
{
}

int KwestDCOPRequest::getHits()
{
	//initiate server but don't go to listen mode.
	appId =DCOPClient::mainClient()->appId();//KApplication::dcopClient->appId();
    	
	//appId = KGlobal::instance()->dcopClient()->appId();
	kdDebug() << "APPid" << appId << endl ;

	//wake up dcop
	bool wake = wakeDCOP();
	if ( !wake )
	{
		kdDebug() << "KwestDCOPRequest::getHits WAKEUP DCOP failed" << endl;
		return -1111;
	}
	
	//clean sockets and get new socket name
	m_socketPath = (QCString) locateLocal("socket",  appId , 1);
    	//m_socketPath = (QCString) "/home/xavier/tmp/socket";
	QString theData = "Socket is " + m_socketPath  + ".\n" ;
	int test =Server::deleteSocket(m_socketPath);
	if ( (test==-2) || (test==-3))
	{
		theData = "\nCannot create socket\n";
		return -112;
	}
	theData = "\nSocket is created\n" +  m_socketPath + (QCString) QString::number(test) + "\n";
       //data(QCString(theData.local8Bit()));

	//init new server    
	m_hitsSocket = new Server(m_socketPath);
	kdDebug() << "kio_kiokwest::getHits()" << endl ;

	bool ok_init = m_hitsSocket ->init();
	kdDebug() << "kio_kiokwest::is server init ok?" << ok_init << endl ;
	if (!ok_init) 
	{
		kdDebug() << "kio_kiokwest::getHits() INIT SERVER FAILED" << endl ;
		return -1112;
	}
    
	//init indexesPathList FIXME: should be read from Config data
	kdDebug() << "kio_kiokwest::DCOP INDEX" << indexesPathList.join(" , ")<<  endl ;
	
	//send query to DCOP DAEMON
	KwestSearchDaemonDCOPIface_stub iface("kwest-search-daemon" , "KwestSearchDaemon");
	//FIXME: DCOp not implemented
	bool peer2peer = TRUE;
	
	int valid = iface.askForNewQuery( m_query, (QCString) m_socketPath ,indexesPathList , 100 , true , peer2peer);
	kdDebug() << "Validity of the dcop query : " << valid << endl ;
	
	// FIXME: better handling of errors from daemon
	// FIXME: I assume only 1 is the correct dcop response, need to handle all correct response cases
	if (valid != 1)
	{
		kdDebug() << "kio_kiokwest::getHits() dcop query not valid/accepted : value : " << valid << endl;
		kdDebug() << "Request from iosalve was : " << m_query << endl;
		return -34;
	}
	
	//goto Listen Mode FIXME:this asumes I have time to go to listen mode before DCOP DAEMON
	m_hitsSocket ->listenAndAccept(); 
    
	QByteArray qbytes_results;
	QByteArray bytes_results;
	//get number of chunks
	//loop over number of chunks
	m_hitsSocket->BigRawDataClientToServer(qbytes_results);
	//uncompress data
	bytes_results = qUncompress(qbytes_results);
	qbytes_results.resize(0);
	m_hitsSocket->getSignal((QString) "The End");
	m_hitsSocket->sendSignal((QString) "The End");
	m_hitsSocket->m_socket->close();
	delete m_hitsSocket;
		
	//Decode data and create file items, the daemon could do it, it would be faster.
// 	MarshallingHelper::undoIt( bytes_results , resultsList);
	QDataStream out(bytes_results, IO_ReadOnly);
	out >>  resultsList;
	kdDebug() << "kio_kiokwest::DCOP INDEX URLS" << resultsList <<  endl ;
	out >>  resultsDisplay;
	kdDebug() << "kio_kiokwest::DCOP INDEX Names" << resultsDisplay <<  endl ;
	out >>  resultsMimeType;
	kdDebug() << "kio_kiokwest::DCOP INDEX mimetype" << resultsMimeType <<  endl ;
	out >>  resultsModTime;
	out >>  resultsMode;
	out >>  resultsSize;
	kdDebug() << "kio_kiokwest::DCOP INDEX mimetype" << resultsSize <<  endl ;
	out >>  resultsStoredPreview;
	kdDebug() << "kio_kiokwest::DCOP INDEX mimetype" << resultsStoredPreview <<  endl ;
// 	out >>  resultsItem;
// 	kdDebug() << "kio_kiokwest::DCOP INDEX mimetype" << resultsItem <<  endl ;

	//processKwestOutput(resultsList);
	emit AllHitsAreHere();	
	this->setQueryFinished(TRUE);
	
	return 1;
}

//decode bytes received from daemon. Any decoding is possible, since the 
//transfer really is byte-aware only
void KwestDCOPRequest::processKwestOutput( QStringList& items)
{
	
	for (QStringList::Iterator it = items.begin(); it != items.end(); ++it) 
	{
		//remove media type and name
		QStringList list = QStringList::split(  "/", *it ,TRUE);
		
		QString path;
		path.append(list.first() + "-");
		list.remove(list.first());
		path.append(list.first() + " ");
		list.remove(list.first());
		
		path = path + list.join("/");
		*it = path;
		kdDebug() << "KwestDCOPRequest::processKwestOutput FOUND: " << path << endl;
	}
	
}

void KwestDCOPRequest::setQuery(QString query)
{
	m_query = query;
}


bool KwestDCOPRequest::isMatching(const QString& /*file*/)
{
	bool matches = true;
 /*   // The file has to belong to our directory.
	matches = file.startsWith(m_locateDirectory);

    // And it has to match against all regular expressions.
	LocateRegExpList::Iterator it = m_regExps.begin();
	for (; matches && (it != m_regExps.end()); ++it) {
	matches = (*it).isMatching(file);
}*/
	return matches;
}

 bool KwestDCOPRequest::wakeDCOP()
{
	int counter = -1;
	// call and wake up the search daemon service 
	kdDebug() << "Start wake up" << endl;
	//if (!m_dcop->isApplicationRegistered("kwest-search-daemon")) 
	if (!DCOPClient::mainClient()->isApplicationRegistered("kwest-search-daemon")) 
	{
		QString error;
		kdDebug() <<  "I have to wake you up\n" << endl;
		if (KApplication::startServiceByDesktopName("kwest_search_daemon", QStringList(),
		    &error , 0  , 0 , 0, TRUE) )
		{
			kdDebug() <<"Starting KwestDcopDaemon failed with message " <<
					error << endl;
			return FALSE;  //bad
		}
		else
		{
			kdDebug() << "Good I did it" << endl;
			while (counter < 5)
			{
				counter++;
				sleep(counter);	
				if (DCOPClient::mainClient()->isApplicationRegistered("kwest-search-daemon")) 
					return TRUE;
			}
			kdDebug() << "Hum I did it, but cannot find its dcop intrerface " << endl;
			return FALSE;
			
		}
		
	}
	else
		kdDebug() << "You are already running !!!" << endl;
	return TRUE;  //good
}

bool KwestDCOPRequest::queryFinished()
{
	return m_finished;
}	
void KwestDCOPRequest::setQueryFinished(bool b)
{
	m_finished = b;
}

int KwestDCOPRequest::start()
{
	kdDebug() << "KwestDCOPRequest::start() STARTING QUERY" << m_query << endl;
	int ok_hits = getHits();
	if (ok_hits == 1)
	{
		kdDebug() << "KwestDCOPRequest::start() Query was a success" << endl;

	}
	else
	{
			kdDebug() << "KwestDCOPRequest::start() Query FAILED with error number " << ok_hits  << endl;

	}
	return ok_hits;
}


#include "kwestdcoprequest.moc"
