#include <iostream.h>
#include <stdlib.h>
#include <qmessagebox.h>
#include <unistd.h>
#include "protmgr.h"
#include "fileprot.h"
#include "mountprot.h"
#include "ftpprot.h"
#include "trashprot.h"
#include "tarprot.h"
#include "zipprot.h"
#include "rpmprot.h"
#include <kapp.h>

ProtocolMgr::ProtocolMgr(QWidget *parent)
{
	protList = new QList<Protocol>;
	protList->setAutoDelete(TRUE);
	tmpList = new QStrList(TRUE);
	ParentWidget = parent;
	activeProtocol = 0;
	dlg = new ProgressDlg(0,"Abort",100,parent,0,TRUE,0);
	dlg->resize(400,150);
//	dlg->setMinimumDuration(500);
	QObject::connect(dlg,SIGNAL(cancelled()),parent,SLOT(abort()));
}

ProtocolMgr::~ProtocolMgr()
{
	QStrListIterator	it(*tmpList);
	for ( ; it.current(); ++it) {
		QString		cmd("rm -rf ");
		cmd += it.current();
		system(cmd.data());
	}
	delete tmpList;
	delete protList;
//	delete dlg;
}

Protocol* ProtocolMgr::searchProtocol(const KURL& url)
{
	QListIterator<Protocol>		it(*protList);
	Protocol	*prot(0);
	int		score(0);
	for ( ; it.current(); ++it)
		if (it.current()->matchURL(url) && it.current()->score() > score) { prot = it.current(); score = it.current()->score();}
if (prot) cout << "protocol : " << prot->prefix() << endl;
else cout << "no protocol found" << endl;
	return prot;
}

void ProtocolMgr::deleteProtocol(KURL& url)
{
	Protocol	*tmp = searchProtocol(url);
	if (tmp) protList->removeRef(tmp);
}

void ProtocolMgr::deleteProtocol(Protocol *prot)
{
	protList->removeRef(prot);
}

Protocol* ProtocolMgr::createProtocol(int type, const char *str1, const char *str2, const char *str3, const char *str4, const char *str5)
{
	Protocol	*prot = 0;
	switch (type) {
	   case Protocol::File: prot = new FileProtocol(str1); break;
	   case Protocol::Mount:
		if (!str1) return 0;
		prot = new MountProtocol(str1,str2,str3);
		break;
	   case Protocol::Ftp:
		if (!str1) return 0;
		prot = new FtpProtocol(str1,str2,str3,str4,str5);
		break;
	   case Protocol::Trash: prot = new TrashProtocol(str1); break;
	   case Protocol::Zip:
	   case Protocol::Rpm:
	   case Protocol::Tar: {
		KURL	url(str1);
		Protocol	*prot2 = searchProtocol(url);
		if (prot2 == 0) return 0;
		if (type == Protocol::Tar) prot = new TarProtocol(getFile(prot2,url),str1);
		else if (type == Protocol::Zip) prot = new ZipProtocol(getFile(prot2,url),str1);
		else if (type == Protocol::Rpm) prot = new RpmProtocol(getFile(prot2,url),str1);
		break;
	   }
	}
	activeProtocol = prot;
	if (!prot->init()) QMessageBox::critical(ParentWidget,i18n("Error"),prot->errorMsg(),QMessageBox::Ok | QMessageBox::Default,0);
	activeProtocol = 0;
	protList->append(prot);
	prot->setupMime(ExtDict,NameDict,Magic,UseMagic);
	prot->setupSubProtList(subProtList);
	return prot;
}

Protocol* ProtocolMgr::createProtocol(KURL& url)
{
	if (strncmp(url.protocol(),"file",4) == 0) return createProtocol(Protocol::File);
//	else if (strncmp(url.protocol(),"ftp",3) == 0) return createProtocol(Protocol::Ftp,url.host(),url.directory(),url.user(),url.passwd());
	else return 0;
}

bool ProtocolMgr::transfer(const char *src, const char *dest, bool needHide, bool move)
{
cout << (move ? "moving " : "copying ") << src << endl << " -> " << dest << endl;
	bool	retval = FALSE, needDel = FALSE;
	KURL	url1(src), url2(dest);
	Protocol	*protDest = searchProtocol(url2), *protSrc = searchProtocol(url1);
	QString		tmp(url2.directory()), tmp2(src);
	tmp += tmp2.right(tmp2.length()-tmp2.findRev('/',tmp2.length()-2)-1);
	if (protDest->exists(tmp.data()) && askOverwrite) {
		QString		msg;
		msg.sprintf("%s already exists. Do you want to replace it ?",tmp.data());
		int	result = QMessageBox::warning(ParentWidget,"Warning",msg.data(),"Yes","Yes to All","Cancel",0);
		switch (result) {
		  case 0 : break;
		  case 1 : askOverwrite = FALSE; break;
		  case 2 : return FALSE;
		}
	}
	if (protSrc == 0) {
		protSrc = createProtocol(url1);
		needDel = TRUE;
	}
	if (protSrc->type() == Protocol::File || protSrc->type() == Protocol::Mount || protSrc->type() == Protocol::Trash) {
		activeProtocol = protDest;
		retval = protDest->copyToProtocol(url1.path(),url2.path(),move,dlg);
	}
	else if (protDest->type() == Protocol::File || protDest->type() == Protocol::Mount || protDest->type() == Protocol::Trash) {
		activeProtocol = protSrc;
		retval = protSrc->copyFromProtocol(url1.path(),url2.path(),move,dlg);
	}
	else {
		QString		tmp(getenv("TMP"));
		if (tmp.isEmpty()) tmp = "/tmp";
		activeProtocol = protSrc;
		retval = protSrc->copyFromProtocol(url1.path(),tmp.data(),move,dlg);
		if (retval) {
			tmp += "/";
			tmp += url1.filename();
			activeProtocol = protDest;
			retval = protDest->copyToProtocol(tmp.data(),url2.path(),move,dlg);
		}
	}
	if (!retval && activeProtocol) QMessageBox::critical(ParentWidget,i18n("Error"),activeProtocol->errorMsg(),QMessageBox::Ok | QMessageBox::Default,0);
	activeProtocol = 0;
	if (needDel) deleteProtocol(protSrc);
	if (needHide) dlg->reset();
	return retval;
}

/*bool ProtocolMgr::copy(Protocol *protSrc, const char *src, Protocol *protDest, const char *dest, bool needHide)
{
	bool	retval = FALSE;
	KURL	url1(src), url2(dest);
	QString		tmp(url2.directory());
	tmp += url1.filename();
	if (protDest->exists(tmp.data()) && askOverwrite) {
		QString		msg;
		msg.sprintf("File %s already exists. Do you want to replace it ?",tmp.data());
		int	result = QMessageBox::warning(ParentWidget,"Warning",msg.data(),"Yes","Yes to All","Cancel",0);
		switch (result) {
		  case 0 : break;
		  case 1 : askOverwrite = FALSE; break;
		  case 2 : return FALSE;
		}
	}
	if (protSrc->type() == Protocol::File || protSrc->type() == Protocol::Mount) {
		activeProtocol = protDest;
		retval = protDest->copyToProtocol(url1.path(),url2.directory(),0,dlg);
		activeProtocol = 0;
	}
	else if (protDest->type() == Protocol::File || protDest->type() == Protocol::Mount) {
		activeProtocol = protSrc;
		retval = protSrc->copyFromProtocol(url1.path(),url2.directory(),0,dlg);
		activeProtocol = 0;
	}
	else {
		QString		tmp(getenv("TMP"));
		if (tmp.isEmpty()) tmp = "/tmp";
		activeProtocol = protSrc;
		retval = protSrc->copyFromProtocol(url1.path(),tmp.data(),0,dlg);
		if (retval) {
			tmp += "/";
			tmp += url1.filename();
			activeProtocol = protDest;
			retval = protDest->copyToProtocol(tmp.data(),url2.directory(),0,dlg);
		}
		activeProtocol = 0;
	}
	if (needHide) dlg->reset();
	return retval;
}*/

bool ProtocolMgr::copy(const QStrList& src, const char *dest)
{
	askOverwrite = TRUE;
	QStrListIterator	it(src);
	bool	retval = FALSE;
	dlg->show();
	for ( ; it.current(); ++it)
		if ((retval = transfer(it.current(),dest,FALSE,FALSE)) == FALSE) break;
	dlg->reset();
	return retval;
}

/*bool ProtocolMgr::copy(const QStrList& src, Protocol *protDest, const char *destDir)
{
	askOverwrite = TRUE;
	QStrListIterator	it(src);
	KURL		url(it.current());
	Protocol	*protSrc = searchProtocol(url);
	bool		needDel = FALSE;
	bool		retval = FALSE;
	if (protSrc == 0) {
		protSrc = createProtocol(url);
		needDel = TRUE;
	}
	for ( ; it.current(); ++it)
		if ((retval = copy(protSrc,it.current(),protDest,destDir,FALSE)) == FALSE) break;
	dlg->reset();
	return retval;
}*/


bool ProtocolMgr::move(const QStrList& src, const char *dest)
{
	askOverwrite = TRUE;
	QStrListIterator	it(src);
	bool	retval = FALSE;
	dlg->show();
	for ( ; it.current(); ++it)
		if ((retval = transfer(it.current(),dest,FALSE,TRUE)) == FALSE) break;
	dlg->reset();
	return retval;
}

const char* ProtocolMgr::getFile(Protocol *prot, KURL& url)
{
	switch(prot->type()) {
	   case Protocol::Trash:
	   case Protocol::Mount:
	   case Protocol::File: return url.path();
	   case Protocol::Ftp: {
		QString		tmp = "/tmp/";
		activeProtocol = prot;
		dlg->show();
		bool	result = prot->copyFromProtocol(url.path(),tmp.data(),0,dlg);
		dlg->reset();
		if (result) {
			tmp += url.filename();
			tmpList->append(tmp.data());
		}
		else QMessageBox::critical(ParentWidget,i18n("Error"),activeProtocol->errorMsg(),QMessageBox::Ok | QMessageBox::Default,0);
		activeProtocol = 0;
		return (result ? tmpList->last() : "");
	   }
	   case Protocol::Zip:
	   case Protocol::Rpm:
	   case Protocol::Tar: {
		QString		tmp("/tmp/");
		activeProtocol = prot;
		dlg->show();
		bool	result = prot->copyFromProtocol(url.path(),tmp.data(),0,dlg);
		dlg->reset();
		if (result) {
			QString		tmpStr(url.url());
			int		pos = tmpStr.findRev(':');
			QString		name = tmpStr.right(tmpStr.length()-pos-1);
			pos = name.find('/');
			if (pos != -1) tmpList->append(QString(tmp + name.left(pos)).data());
			tmp += name;
			tmpList->append(tmp.data());
		}
		else QMessageBox::critical(ParentWidget,i18n("Error"),activeProtocol->errorMsg(),QMessageBox::Ok | QMessageBox::Default,0);
		activeProtocol = 0;
		return (result ? tmpList->last() : "");
	   }
	}
	return 0;
}

const char *ProtocolMgr::getFile(const char *url)
{
	KURL		Url(url);
	Protocol	*prot = searchProtocol(Url);
	if (prot != 0) return getFile(prot,Url);
	else return 0;
}

const FileInfoList* ProtocolMgr::list(Protocol *prot, KURL& url, bool hidden, bool dirsOnly, bool showArchive)
{
	activeProtocol = prot;
	QString		RealPath;
	if (url.hasSubProtocol()) {
		QString	str(url.childURL().data());
		int	pos = str.findRev(':');
		RealPath = str.right(str.length()-pos-1);
	}
	else RealPath = url.path();
	if (prot->setPath(RealPath.data())) {
		const FileInfoList	*tmp = prot->entryInfoList(hidden,dirsOnly,showArchive);
		activeProtocol = 0;
		return tmp;
	}
	else {
		activeProtocol = 0;
		return 0;
	}
}

const FileInfoList* ProtocolMgr::list(const char *url, bool hidden, bool dirsOnly, bool showArchive)
{
	KURL	URL(url);
	Protocol	*prot = searchProtocol(URL);
	if (prot != 0) return list(prot,URL,hidden,dirsOnly,showArchive);
	else return 0;
}

void ProtocolMgr::abort()
{
cout << "aborting" << endl;
	if (activeProtocol != 0) activeProtocol->abort();
}

bool ProtocolMgr::rename(Protocol *prot, const KURL& src, const KURL& dest)
{
	activeProtocol = prot;
	bool	tmp = prot->rename(src.path(),dest.path());
	activeProtocol = 0;
	return tmp;
}

bool ProtocolMgr::rename(const char *src, const char *dest)
{
	KURL		Src(src),Dest(dest);
	Protocol	*prot = searchProtocol(Src);
	if (prot != 0) return rename(prot,Src,Dest);
	else return FALSE;
}

bool ProtocolMgr::remove(Protocol *prot, const KURL& url)
{
	activeProtocol = prot;
	bool	tmp = prot->remove(url.path());
	activeProtocol = 0;
	return tmp;
}

bool ProtocolMgr::remove(const char *url)
{
	KURL	Url(url);
	Protocol	*prot = searchProtocol(Url);
	if (prot) return remove(prot,Url);
	else return FALSE;
}

bool ProtocolMgr::rmdir(Protocol *prot, const KURL& url)
{
	activeProtocol = prot;
	dlg->show();
	bool	tmp = prot->rmdir(url.path(),dlg);
	activeProtocol = 0;
	dlg->reset();
	return tmp;
}

bool ProtocolMgr::rmdir(const char *url)
{
	KURL	Url(url);
	Protocol	*prot = searchProtocol(Url);
	if (prot) return rmdir(prot,Url);
	else return FALSE;
}

bool ProtocolMgr::chmod(Protocol *prot, const KURL& url, int perm)
{
	activeProtocol = prot;
	bool	tmp = prot->chmod(url.path(),perm);
	activeProtocol = 0;
	return tmp;
}

bool ProtocolMgr::chmod(const char *url, int perm)
{
	KURL	Url(url);
	Protocol	*prot = searchProtocol(Url);
	if (prot) return chmod(prot,Url,perm);
	else return FALSE;
}

bool ProtocolMgr::mkdir(Protocol *prot, const KURL& url)
{
	activeProtocol = prot;
	bool	tmp = prot->mkdir(url.path());
	activeProtocol = 0;
	return tmp;
}

bool ProtocolMgr::mkdir(const char *url)
{
	KURL	Url(url);
	Protocol	*prot = searchProtocol(Url);
	if (prot) return mkdir(prot,Url);
	else return FALSE;
}

void ProtocolMgr::setupMime(KMimeExtDict *extDict, KMimeExtList *nameDict, MimeMagic *magic, bool use)
{
	ExtDict = extDict;
	NameDict = nameDict;
	Magic = magic;
	UseMagic = use;
	QListIterator<Protocol>		it(*protList);
	for (;it.current();++it) it.current()->setupMime(ExtDict,NameDict,Magic,UseMagic);
}

void ProtocolMgr::setupSubProtList(SubProtList *list)
{
	subProtList = list;
	QListIterator<Protocol>		it(*protList);
	for (;it.current();++it) it.current()->setupSubProtList(list);
}

bool ProtocolMgr::emptyTrash(Protocol *prot)
{
	activeProtocol = prot;
	dlg->show();
	bool	tmp = ((TrashProtocol*)prot)->empty(dlg);
	activeProtocol = 0;
	dlg->reset();
	return tmp;
}
