/***************************************************************************
 *   Copyright (C) 2005 by Diego 'Flameeyes' Pettenò   *
 *   flameeyes@gentoo.org   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library 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 Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "kio_atmosphereprotocol.h"

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

#include <qdir.h>
#include <qstringlist.h>

#include <sys/stat.h>

#include "atmosserver_stub.h"

extern "C" {
	int KDE_EXPORT kdemain( int argc, char **argv )
	{
		KLocale::setMainCatalogue("kdelibs");
		KInstance instance( "kio_file" );
		( void ) KGlobal::locale();
		
		if (argc != 4)
		{
			fprintf(stderr, "Usage: kio_atmosphere protocol domain-socket1 domain-socket2\n");
			exit(-1);
		}

		kio_atmosphereProtocol slave( argv[2], argv[3] );
		slave.dispatchLoop();
		return 0;
	}
}

kio_atmosphereProtocol::kio_atmosphereProtocol(const QCString &pool_socket, const QCString &app_socket)
 : KIO::SlaveBase("atmosphere", pool_socket, app_socket)
{
	kdDebug(210000) << "kio_atmosphereProtocol::kio_atmosphereProtocol()" << endl;
	KApplication::dcopClient()->attach();
	
	m_serv = new ATMOSserver_stub("atmosphere", "ATMOSserver");
}

kio_atmosphereProtocol::~kio_atmosphereProtocol()
{
	kdDebug(210000) << "kio_atmosphereProtocol::~kio_atmosphereProtocol()" << endl;
	
	delete m_serv;
}

void kio_atmosphereProtocol::get( const KURL &url )
{
	QString path = QDir::cleanDirPath( url.path() );
	
	kdDebug(210000) << "atmosphere get [" << path << "]" << endl;

	QStringList pathlist = QStringList::split("/", url.path());
	switch(pathlist.count())
	{
	case 0:
	case 1:
		error( KIO::ERR_IS_DIRECTORY, url.prettyURL() );
		return;
	case 2:
		if ( pathlist[1] == "Samba Shares" )
			redirection( KURL("smb://" + m_serv->getBoxHost(pathlist[0]) + "/") );
	}
	finished();
}

void kio_atmosphereProtocol::listDir( const KURL &url )
{
	kdDebug(210000) << "atmosphere listDir() " << url << " -- start" << endl;

	QStringList pathlist = QStringList::split("/", url.path());
	switch(pathlist.count())
	{
	case 0: {
			QStringList reply = m_serv->getBoxesNames();
	
			if ( m_serv->status() == DCOPStub::CallFailed )
				error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
			
			totalSize(reply.size());
			for(QStringList::Iterator it = reply.begin(); it != reply.end(); it++)
			{
				listEntry( createBoxEntry(*it), false );
				listEntry( KIO::UDSEntry(), true );
			}
		}
	case 1:
		listInsideBox(pathlist[0]);
		break;
	default:
		error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
	}

	finished();
	kdDebug(210000) << "atmosphere listDir() -- end" << endl;
}

void kio_atmosphereProtocol::stat( const KURL &url )
{
	QString path = QDir::cleanDirPath( url.path() );
	
	kdDebug(210000) << "atmosphere stat [" << path << "]" << endl;

	QStringList pathlist = QStringList::split("/", url.path());
	switch(pathlist.count())
	{
	case 0:
		// When requesting 'atmosphere:/', load boxes
		m_serv->loadBoxes();
		statEntry( createDirEntry( "", "boxes" ) );
		break;
	case 1:
		statEntry( createBoxEntry( pathlist[0], true ) );
		break;
	}

	finished();
	kdDebug(210000) << "atmosphere stat() -- end" << endl;
}

void kio_atmosphereProtocol::rename( const KURL &src, const KURL &dest, bool overwrite )
{
	QString srcpath = QDir::cleanDirPath( src.path() );
	QString destpath = QDir::cleanDirPath( dest.path() );
	
	if ( srcpath == destpath ) return;
	
	/* Strip leading / */
	if ( srcpath.startsWith("/") ) srcpath.remove(0, 1);
	if ( destpath.startsWith("/") ) destpath.remove(0, 1);
	
	/* Can't use directories here */
	if ( destpath.contains('/') )
	{
		error( KIO::ERR_CANNOT_RENAME, src.path() );
		return;
	}
	
	if ( m_serv->renameBox(srcpath, destpath) )
		finished();
	else
		error( KIO::ERR_CANNOT_RENAME, src.path() );
	return;
}

void kio_atmosphereProtocol::del( const KURL &url, bool isfile )
{
	QString path = QDir::cleanDirPath( url.path() );
	
	QStringList pathlist = QStringList::split("/", url.path());
	switch(pathlist.count())
	{
	case 1:
		if ( ! m_serv->deleteBox(pathlist[0]) )
		{
			error( KIO::ERR_UNSUPPORTED_ACTION, url.path() );
			return;
		}
		break;
	default:
		error( KIO::ERR_UNSUPPORTED_ACTION, url.path() );
		return;
	}

	finished();
}

#define fillatom(ENTRY, UDS, VAL, STR) \
	{ \
		KIO::UDSAtom atom; \
		atom.m_uds = UDS; \
		atom.VAL = STR; \
		ENTRY.append(atom); \
	}

KIO::UDSEntry kio_atmosphereProtocol::createBoxEntry(const QString &boxname, bool stat)
{
	KIO::UDSEntry entry = createDirEntry(boxname, m_serv->isBoxUp(boxname) ? "boxup" : "boxdown");
	fillatom(entry, KIO::UDS_MIME_TYPE, m_str, "application/x-atmosphere");
	return entry;
}

KIO::UDSEntry kio_atmosphereProtocol::createDirEntry(const QString &dirname, const QString &icon)
{
	KIO::UDSEntry entry;
	
	// Set the name specified
	fillatom(entry, KIO::UDS_NAME, m_str, dirname);
	
	// Set full access
	fillatom(entry, KIO::UDS_ACCESS, m_long, S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
	
	// Set the icon name depending on the status
	fillatom(entry, KIO::UDS_ICON_NAME, m_str, icon);

	fillatom(entry, KIO::UDS_FILE_TYPE, m_long, S_IFDIR);

	fillatom(entry, KIO::UDS_USER, m_str, "root");
	fillatom(entry, KIO::UDS_GROUP, m_str, "root");

	return entry;
}

void kio_atmosphereProtocol::listInsideBox(const QString &boxname)
{
	kdDebug(210000) << "boxname: " << boxname << endl;
	// Only if the box is up show the interfaces
	if ( m_serv->isBoxUp(boxname) )
	{
		// Interfaces subdir with statistics about interfaces
		listEntry(createDirEntry("Interfaces", "interfaces"), false);

		listEntry(createDirEntry("Samba Shares", "samba"), false);
	}

	listEntry(KIO::UDSEntry(), true);
}
