/***************************************************************************
 *   Copyright (C) 2005 by Bastian Holst                                   *
 *   bastianholst@gmx.de                                                   *
 *   Copyright (C) 2006 by Martin Meredith                                 *
 *   mez@thekatapult.org.uk                                                *
 *                                                                         *
 *   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 <tdeapplication.h>
#include <tdesycocaentry.h>
#include <tdesycocatype.h>
#include <knuminput.h>
#include <kurl.h>
#include <tqstring.h>
#include <tqcstring.h>
#include <tqstringlist.h>
#include <tqdatastream.h>
#include <dcopclient.h>
#include <tqregexp.h>

#include "actionplaysong.h"
#include "song.h"
#include "amarokcatalog.h"
#include "actionregistry.h"
#include "status.h"
#include "settings.h"

K_EXPORT_COMPONENT_FACTORY( katapult_amarokcatalog,
                           KGenericFactory<AmarokCatalog>( "katapult_amarokcatalog" ) )

AmarokCatalog::AmarokCatalog(TQObject*, const char*, const TQStringList&): _result(TQString()) 
{
	_minQueryLen = 3;
	ActionRegistry::self()->registerAction(new ActionPlaySong());
	_gotCollectionStatus = false;
	_dynamicCollection = false;
	checkCollectionType();	

}
AmarokCatalog::~AmarokCatalog()
{
}

void AmarokCatalog::queryChanged()
{
	int newStatus = 0;
	TQString queryString = query();
	
	if((TQString(queryString).remove(':').remove('\"').remove(' ').isEmpty()) || (queryString.length() < _minQueryLen)) {
		reset();
		setBestMatch(Match());
		setStatus(0);
	} else {

		if ( _gotCollectionStatus)
		{

			if (!_dynamicCollection)
			{

			// Stuff for Amarok < 1.4.2

				TQStringList queryList;
				//prepares SQL-queryTQRegExp
				TQString sqlQuery(
					"SELECT artist.name, tags.title, tags.url, images.path, album.name "
					"FROM tags"
					"INNER JOIN album ON (tags.album = album.id) "
					"INNER JOIN artist ON (tags.artist = artist.id) "
					"LEFT JOIN statistics ON (tags.url = statistics.url) "
					"LEFT JOIN images ON (artist.name = images.artist AND album.name = images.album) "
					"WHERE 1=1 "
				);// AND
		
				queryList = TQStringList::split ( TQString(" "), TQString(queryString).replace(TQChar(':')," ").replace(TQChar('\''), " ").replace(TQChar('\''), "%") );	
				for(TQStringList::Iterator it = queryList.begin(); it != queryList.end(); ++it) {
					sqlQuery.append(TQString(" AND (t.title LIKE '\%%1\%'").arg(*it));
					sqlQuery.append(TQString(" OR a.name LIKE '\%%1\%')").arg(*it));
				}
				sqlQuery.append(" ORDER BY a.name, t.title, s.percentage DESC");
				
				//sending SQL-query to ararok via dcop
				TQByteArray sqlQueryData, replyData;
				TQCString replyType;
				TQDataStream arg(sqlQueryData, IO_WriteOnly);
				arg << sqlQuery;
				if (!tdeApp->dcopClient()->call("amarok", "collection", "query(TQString)",
				     sqlQueryData, replyType, replyData)) {
					newStatus = 0;
				} else {
					TQDataStream reply(replyData, IO_ReadOnly);
					if (replyType == "TQStringList") {
						TQStringList sqlResult;
						reply >> sqlResult;
					
						if(sqlResult.isEmpty()) {
							newStatus = 0;
						} else {
							reset();
							//Reads information from SQL-Query
							_result.setArtist(sqlResult[0]);
							_result.setName(sqlResult[1]);
							_result.setURL(KURL(sqlResult[2]));
							_result.setAlbum(sqlResult[4]);
						
							//_result.setIcon(TQString());
							if ( !sqlResult[3].isEmpty() ) {
								_result.setIcon(sqlResult[3]);
							}
							
							//counts the matched charecters
							int i = queryString.find( ':' );
							if ( i != -1 ) {
								if ( queryString[i+1] != ' ' )
									queryString.insert(i+1, ' ');
								if ( queryString[i-1] != ' ' ) 
									queryString.insert(i, ' ');
							}
							queryList = TQStringList::split ( " ", queryString );
							unsigned int matched = 0;
							for(TQStringList::Iterator it = queryList.begin(); it != queryList.end(); ++it) {
								if(matched < (_result.text().find(*it, matched, false) + (*it).length()))
									matched = _result.text().find(*it, matched, false) + (*it).length();
							}
							setBestMatch(Match(&_result, 100*queryString.length()/_result.text().length(), matched)); 
					
							//Checks if there are multiple results
							if( !sqlResult[5].isEmpty() )
								newStatus = S_HasResults | S_Multiple;
							else 
								newStatus = S_HasResults;
						}
					} else {
						newStatus = 0;
					}
				}

			} else {	// Dynamic Collection 

				// Do same as above here again but with dyn collection stuff

				TQStringList queryList;
				//prepares SQL-queryTQRegExp
				TQString sqlQuery("SELECT a.name, t.title, t.deviceid, d.lastmountpoint, t.url, i.path, album.name FROM tags t LEFT JOIN statistics s ON (t.url = s.url AND t.deviceid = s.deviceid) LEFT JOIN artist a ON (t.artist = a.id) LEFT JOIN album ON (t.album = album.id) LEFT JOIN images i ON ( a.name = i.artist AND album.name = i.album) LEFT JOIN devices d ON (t.deviceid = d.id) WHERE ");
				queryList = TQStringList::split ( TQString(" "), TQString(queryString).replace(TQChar(':')," ").replace(TQChar('\''), " ").replace(TQChar('\''), "%") );

        // Let's build each of these clauses
        TQStringList clauses;
				for(TQStringList::Iterator it = queryList.begin(); it != queryList.end(); ++it) {

					clauses += TQString(" (t.title LIKE '\%%1\%'").arg(*it) +
            TQString(" OR a.name LIKE '\%%1\%')").arg(*it);
				}
        sqlQuery.append(clauses.join(TQString(" AND ")));
				sqlQuery.append(" ORDER BY a.name, t.title, s.percentage DESC");
				
				//sending SQL-query to ararok via dcop
				TQByteArray sqlQueryData, replyData;
				TQCString replyType;
				TQDataStream arg(sqlQueryData, IO_WriteOnly);
				arg << sqlQuery;
				if (!tdeApp->dcopClient()->call("amarok", "collection", "query(TQString)",
				     sqlQueryData, replyType, replyData)) {
					newStatus = 0;
				} else {
					TQDataStream reply(replyData, IO_ReadOnly);
					if (replyType == "TQStringList") {
						TQStringList sqlResult;
						reply >> sqlResult;
					
						if(sqlResult.isEmpty()) {
							newStatus = 0;
						} else {
							reset();
							//Reads information from SQL-Query
							_result.setArtist(sqlResult[0]);
							_result.setName(sqlResult[1]);
							if (sqlResult[2]!="-1") {
								KURL absolutePath;
								absolutePath.setPath( sqlResult[3] );
								absolutePath.addPath( sqlResult[4] );
								absolutePath.cleanPath();

								_result.setURL( absolutePath );
							} else {
								KURL absolutePath;
								absolutePath.setPath( "/" );
								absolutePath.addPath( sqlResult[4] );
								absolutePath.cleanPath(); 

								_result.setURL( absolutePath );
							}

							_result.setAlbum(sqlResult[6]);
						
							//_result.setIcon(TQString());
							if ( !sqlResult[3].isEmpty() ) {
								_result.setIcon(sqlResult[5]);
							}
							
							//counts the matched charecters
							int i = queryString.find( ':' );
							if ( i != -1 ) {
								if ( queryString[i+1] != ' ' )
									queryString.insert(i+1, ' ');
								if ( queryString[i-1] != ' ' ) 
									queryString.insert(i, ' ');
							}
							queryList = TQStringList::split ( " ", queryString );
							unsigned int matched = 0;
							for(TQStringList::Iterator it = queryList.begin(); it != queryList.end(); ++it) {
								if(matched < (_result.text().find(*it, matched, false) + (*it).length()))
									matched = _result.text().find(*it, matched, false) + (*it).length();
							}
							setBestMatch(Match(&_result, 100*queryString.length()/_result.text().length(), matched)); 
					
							//Checks if there are multiple results
						 	if( !sqlResult[7].isEmpty() )
								newStatus = S_HasResults | S_Multiple;
							else 
								newStatus = S_HasResults;
						}
					} else {
						newStatus = 0;
					}
				}


			} //end of >1.4.2 section
		setStatus(newStatus);

		} else {                //We haven't got the collection status

			checkCollectionType();	
			reset();
			setBestMatch(Match());
			setStatus(0);
		}


	} //dont go after this while fixing

}

void AmarokCatalog::reset()
{
	_result.setName(TQString());
	_result.setArtist(TQString());
	_result.setAlbum(TQString());
	_result.setIcon(TQString());
}

void AmarokCatalog::checkCollectionType()
{
	TQString sqlQuery("SELECT COUNT(*) FROM admin WHERE noption = 'Database Devices Version'");

	TQByteArray sqlQueryData, replyData;
	TQCString replyType;
	TQDataStream arg(sqlQueryData, IO_WriteOnly);
	arg << sqlQuery;
	if (!tdeApp->dcopClient()->call("amarok", "collection", "query(TQString)", sqlQueryData, replyType, replyData))
	{
		_gotCollectionStatus = false;

	}
	else
	{
		TQDataStream reply(replyData, IO_ReadOnly);
		if (replyType == "TQStringList")
		{
			TQStringList sqlResult;
			reply >> sqlResult;

			if (sqlResult[0] == "1")
			{
				_dynamicCollection = true;

			}
			else
			{
				_dynamicCollection = false;

			}
			_gotCollectionStatus = true;
		}
		else
		{
			_gotCollectionStatus = false;
		}
	}
}


/*
void AmarokCatalog::initialize()
{
}
*/

unsigned int AmarokCatalog::minQueryLen() const
{
	return _minQueryLen;
}

TQWidget * AmarokCatalog::configure()
{
	AmarokCatalogSettings *settings = new AmarokCatalogSettings();
	
	settings->minQueryLen->setValue(_minQueryLen);
	connect(settings->minQueryLen, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(minQueryLenChanged(int)));
	return settings;
}

void AmarokCatalog::minQueryLenChanged(int _minQueryLen)
{
	this->_minQueryLen = _minQueryLen;
}

void AmarokCatalog::readSettings(TDEConfigBase *config)
{
	_minQueryLen = config->readUnsignedNumEntry("MinQueryLen", 3);
}

void AmarokCatalog::writeSettings(TDEConfigBase *config)
{
	config->writeEntry("MinQueryLen", _minQueryLen);
}

#include "amarokcatalog.moc"
