/*
 *
 *  Kepas - KDE Easy Publish and Share
 *
 *  Copyright (C) 2008  Tom Patzig <tpatzig@suse.de>
 *
 *  This file is part of kepas.
 *
 *  kepas 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.
 *
 *  kepas 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 kepas; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
*/

#include "plasma-kifer.h"
#include <QPainter>
#include <QSizeF>
#include <KIcon>
 
#include <plasma/svg.h>
#include <plasma/theme.h>
#include <plasma/widgets/iconwidget.h>
#include <plasma/containment.h>

using namespace KPF;
 
PlasmaKifer::PlasmaKifer(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args),
    m_icon(0)
{
	setHasConfigurationInterface(true);
	m_dialog = 0;
	publicServerWiz = 0;
	configDialog = 0;

    setAspectRatioMode(Plasma::ConstrainedSquare);
    setBackgroundHints(NoBackground);
    m_icon = new Plasma::IconWidget(KIcon("folder-remote"),QString(),this);
    m_icon->setNumDisplayLines(1);
    m_icon->setDrawBackground(true);
    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);

    layout->addItem(m_icon);

    resize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));

}

void PlasmaKifer::init()
{
	buddylist = new BuddyList(this);
	avahiClient = new ServiceLocator(this);
//	connect(avahiClient, SIGNAL(serviceRuns()),this, SLOT(failedToStart()));

	createMenu();
	connect(m_icon, SIGNAL(pressed(bool)),this, SLOT(popup(bool)));
	connect(&m_menu, SIGNAL(aboutToHide()),m_icon, SLOT(setUnpressed()));

	setAcceptDrops(true);
	setAcceptsHoverEvents(true);

	webServerHash = new QHash<QString, WebServer*>;
	webServerMenuHash = new QHash<QString, QMenu*>;
	actionHash = new QHash<QString, QAction*>;

	config = new KConfig("kepasrc");
	confGroup = new KConfigGroup(config,"General");

	if (confGroup->exists()) {
		avahiClient->receiver->setTargetPath(confGroup->readEntry("Path",avahiClient->receiver->getTargetPath()));
		avahiClient->setUserName(confGroup->readEntry("Nick",avahiClient->getUserName()));
	}
	avahiClient->startService();

}
 
PlasmaKifer::~PlasmaKifer()
{

    if (m_dialog)
	delete m_dialog;
	qDebug() << "m_dialog deleted";

    if (buddylist)
	delete buddylist;
	qDebug() << "buddylist deleted";
    if (avahiClient)
	delete avahiClient;
	qDebug() << "avahiclient deleted";

	qDeleteAll (webServerHash->begin(),webServerHash->end());
	delete webServerHash;
	kDebug() << "webServerHash completly deleted";

	qDeleteAll (actionHash->begin(),actionHash->end());
	delete actionHash;
	kDebug() << "actionHash completly deleted";

	qDeleteAll (webServerMenuHash->begin(),webServerMenuHash->end());
	delete webServerMenuHash;
	kDebug() << "webServerMenuHash completly deleted";
	
	delete config;
	delete confGroup;

     delete dbus;
}

void PlasmaKifer::failedToStart()
{
	m_icon->setIcon(KIcon("dialog-information"));
	m_icon->setText("Service already running");
	m_menu.clear();
}

void PlasmaKifer::constraintsEvent(Plasma::Constraints constraints)
{
	setBackgroundHints(NoBackground);

    if (constraints & Plasma::FormFactorConstraint) {
		disconnect(m_icon, SIGNAL(pressed(bool)),this, SLOT(popup(bool)));

        if (formFactor() == Plasma::Planar ||
            formFactor() == Plasma::MediaCenter) {
	    	connect(m_icon, SIGNAL(pressed(bool)),this, SLOT(popup(bool)));
            m_icon->setText(i18n("Kepas"));
	 	 	m_icon->setDrawBackground(true);
            setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));
        } else {
	    connect(m_icon, SIGNAL(pressed(bool)),this, SLOT(popup(bool)));
            m_icon->setText(QString());
//          m_icon->setInfoText(QString());
            setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Small)));
	 	 	m_icon->setDrawBackground(false);
        }
    }

}

void PlasmaKifer::createMenu()
{
    QAction* buddies = new QAction(KIcon("user-identity"),i18n("Buddies"), this);
    connect(buddies, SIGNAL(triggered(bool)), this , SLOT(slotBuddyList(bool)));

    QAction* sendFile = new QAction(KIcon("text-directory"),i18n("Send File"), this);
    connect(sendFile, SIGNAL(triggered(bool)), this , SLOT(slotFileSelect(bool)));

    QAction* newServerAction = new QAction(KIcon("network-server"), i18n("New Server"),this);
    connect(newServerAction, SIGNAL(triggered(bool)), this, SLOT(slotServerWizard(bool)));

    m_menu.addTitle(i18n("Kepas"));
    m_menu.addAction(buddies);
    m_menu.addAction(sendFile);
    clipMenu = m_menu.addMenu(KIcon("klipper"),i18n("Send Clipboard"));
    addClipEntries();
    kpfMenu = m_menu.addMenu(KIcon("network-server"), i18n("Public Server"));
    kpfMenu->addAction(newServerAction);


}

void PlasmaKifer::popup(bool pressed)
{
    if (!pressed || m_menu.isVisible()) {
        m_menu.hide();
        return;
    }
/*
    QPointF scenePos = mapToScene(boundingRect().topLeft());
    QGraphicsView *viewWidget = view();
    QDesktopWidget *desktop = QApplication::desktop();
    if (viewWidget) {
        QPoint viewPos = viewWidget->mapFromScene(scenePos);
        QPoint globalPos = viewWidget->mapToGlobal(viewPos);
        QRect desktopRect = desktop->availableGeometry(viewWidget);
        QRect size = mapToView(viewWidget, contentRect());

        const int menuHeight = m_menu.sizeHint().height();

        if (globalPos.y() + size.height() + menuHeight
            < desktopRect.bottom()) {
            globalPos.ry() += geometry().size().height();
        }else{
            globalPos.ry() -= menuHeight;
        }
//      m_menu.popup(globalPos);
*/
        m_menu.popup(popupPosition(m_menu.sizeHint()));
        m_icon->setPressed();
//    }
    	addClipEntries();
}

void PlasmaKifer::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
        kDebug() << event->mimeData()->formats();

        if (event->mimeData()->hasUrls()) {
                event->acceptProposedAction();
        }
        else {
         event->ignore();
        }

}

void PlasmaKifer::dropEvent(QGraphicsSceneDragDropEvent *event)
{
        KUrl droppedUrl = (KUrl::List::fromMimeData(event->mimeData())).at(0);
	QString file = droppedUrl.toLocalFile();
	
        avahiClient->browse();
        connect(avahiClient, SIGNAL(addBuddy(QMap<QString, QByteArray>)),buddylist,SLOT(addService(QMap<QString,QByteArray>)));
        connect(avahiClient, SIGNAL(delBuddy(QString)),buddylist,SLOT(delService(QString)));
        buddylist->initSendFileBuddyList(file,avahiClient->getUserName());
	
}

void PlasmaKifer::slotBuddyList(bool set)
{

	 avahiClient->browse();
	 connect(avahiClient, SIGNAL(addBuddy(QMap<QString, QByteArray>)),buddylist,SLOT(addService(QMap<QString,QByteArray>)));
	 connect(avahiClient, SIGNAL(delBuddy(QString)),buddylist,SLOT(delService(QString)));

	 avahiClient->httpBrowse();
	 connect(avahiClient, SIGNAL(httpFound(QString,QString)),buddylist,SLOT(addHttpService(QString,QString)));
	 connect(avahiClient, SIGNAL(httpRemoved(QString)),buddylist,SLOT(delHttpService(QString)));

	 
	 buddylist->initDefaultBuddyList(avahiClient->getUserName());

}

void PlasmaKifer::slotFileSelect(bool set)
{

	QString fileName = KFileDialog::getOpenFileName(KUrl("./"),"*",&m_menu, tr("Select File"));
	if (fileName.isEmpty())
		return;
	else {
		avahiClient->browse();
		connect(avahiClient, SIGNAL(addBuddy(QMap<QString, QByteArray>)),buddylist,SLOT(addService(QMap<QString,QByteArray>)));
		connect(avahiClient, SIGNAL(delBuddy(QString)),buddylist,SLOT(delService(QString)));
	
        	buddylist->initSendFileBuddyList(fileName,avahiClient->getUserName());
	}
}


void PlasmaKifer::showConfigurationInterface()
{
   QString target = confGroup->readEntry("Path",avahiClient->receiver->getTargetPath());
   QString nick = confGroup->readEntry("Nick",avahiClient->getUserName());

   if (m_dialog == 0) {
        m_dialog = new KDialog;
        m_dialog->setCaption( i18n("Configure Kepas") );
        ui.setupUi(m_dialog->mainWidget());
        m_dialog->setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply );
        connect( m_dialog, SIGNAL(applyClicked()), this, SLOT(configAccepted()) );
        connect( m_dialog, SIGNAL(okClicked()), this, SLOT(configAccepted()) );
	connect( ui.saveToButton,SIGNAL(clicked()),this,SLOT(slotSelectDir()));
    }
    ui.pictureButton->setIcon(KIcon("user-identity"));
    ui.nameLineEdit->setText(nick);
    ui.saveToLineEdit->setText(target);
 
    
    m_dialog->show();
}

void PlasmaKifer::configAccepted()
{
	confGroup->writeEntry("Path",ui.saveToLineEdit->text());
	confGroup->writeEntry("Nick",ui.nameLineEdit->text());

	avahiClient->receiver->setTargetPath(ui.saveToLineEdit->text());
	avahiClient->setUserName(ui.nameLineEdit->text());
	bool OK = avahiClient->restartPublish();
        OK ? qDebug() << "Service restarted and published succesfull " : qDebug() << "Service not published";
	
}

void PlasmaKifer::slotSelectDir()
{

	QString dirname = KFileDialog::getExistingDirectory(KUrl("./"),&m_menu, tr("Select Target Directory"));
	if (!dirname.isEmpty())
		ui.saveToLineEdit->setText(dirname);

}

void PlasmaKifer::addClipEntries()
{
	clipMenu->clear();
	dbus = new QDBusConnection("dbus");
	QDBusConnection dbusconn = dbus->connectToBus(QDBusConnection::SessionBus, "dbus");
	QString service = "org.kde.klipper";
	QString path = "/klipper";
	QString method = "getClipboardHistoryMenu";
	QString service2 = "org.kde.klipper.klipper";

	QDBusInterface* interface = new QDBusInterface(service,path,service2,dbusconn);
	QDBusReply<QStringList> reply = interface->call(method);
	
//	qDebug() << "klipper reply: " << reply.value();
	QStringList clipList = reply.value();

	for (int i=0; i < clipList.size(); i++){
		if (clipList.at(i).size() >= 30) {
			QString cut = clipList.at(i);
			cut.truncate(30);
			
			clipAction = clipMenu->addAction(cut + " ...");
	         } else
			clipAction = clipMenu->addAction(clipList.at(i));
		
		clipAction->setToolTip(clipList.at(i));
		
	}

 	connect(clipMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotSendClipEntry(QAction*)));
}

void PlasmaKifer::slotSendClipEntry(QAction* action)
{
	avahiClient->browse();
	connect(avahiClient, SIGNAL(addBuddy(QMap<QString, QByteArray>)),buddylist,SLOT(addService(QMap<QString,QByteArray>)));
	connect(avahiClient, SIGNAL(delBuddy(QString)),buddylist,SLOT(delService(QString)));

	QString entry = action->toolTip();
	buddylist->initSendClipBuddyList(entry,avahiClient->getUserName());

}

void PlasmaKifer::slotServerWizard(bool set)
{
	publicServerWiz = new ServerWizard((QWidget*)&m_menu);
	connect(publicServerWiz,SIGNAL(dying(ServerWizard*)),SLOT(slotWizardDying(ServerWizard*)));
	publicServerWiz->show();
}

void PlasmaKifer::slotWizardDying(ServerWizard * wiz)
{
	kDebug() << "wizard finished";
	kDebug() << "ROOOT: " << wiz->root();

	QString dir = wiz->root();
	QString leer = "";
    	dir.replace(0,7,leer);
    if (QDialog::Accepted == wiz->result())
    {
	QTcpServer test;
	bool portFree = test.listen(QHostAddress::Any,wiz->listenPort());
	if (!portFree) {
		KMessageBox::error(&m_menu,i18n("Failed to bind port %1",(QString::number(wiz->listenPort()))));	
		return;
	}
	test.close();

	webSrv = new WebServer(
			 dir,
			 wiz->listenPort(),
			 wiz->bandwidthLimit(),
			 wiz->connectionLimit(),
			 Config::DefaultFollowSymlinks,
			 wiz->serverName()
	);
	newServerMenu = kpfMenu->addMenu(KIcon("user-online"), QString("%1:%2").arg(wiz->serverName()).arg(wiz->listenPort()));
	connect(newServerMenu,SIGNAL(triggered(QAction*)),this,SLOT(slotServerMenuTriggered(QAction*)));
	
	monitorAction = newServerMenu->addAction(KIcon("utilities-system-monitor"), i18n("Monitor"));
	pauseAction = newServerMenu->addAction(KIcon("media-playback-pause"), i18n("Pause"));
	removeAction = newServerMenu->addAction(KIcon("dialog-close"), i18n("Remove"));
	restartAction = newServerMenu->addAction(KIcon("view-refresh"), i18n("Restart"));
	prefAction = newServerMenu->addAction(KIcon("preferences-system-network"), i18n("Preferences"));
	
	actionHash->insertMulti(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),monitorAction);
	actionHash->insertMulti(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),pauseAction);
	actionHash->insertMulti(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),removeAction);
	actionHash->insertMulti(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),restartAction);
	actionHash->insertMulti(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),prefAction);

	webServerHash->insert(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),webSrv);
	webServerMenuHash->insert(QString(wiz->serverName() + ":" + QString::number(wiz->listenPort())),newServerMenu);

	
    }

    delete publicServerWiz;
    publicServerWiz = 0;
}


void PlasmaKifer::slotMonitorAction(QAction* ac)
{
	kDebug() << "slotMonitorAction" ;
	QMenu* men = (QMenu*)ac->parentWidget();
	QString serverName = men->title();
	kDebug() << "ServerName: "<< serverName ;
	kDebug() << "Server: "<< men->title() ;

	WebServer* srv = webServerHash->value(serverName);		
	kDebug() << srv->serverName();

	ActiveMonitorWindow* monitorWindow = new ActiveMonitorWindow(srv);
	monitorWindow->show();
	monitorWindow->raise();

}

void PlasmaKifer::slotRemoveServerAction(QAction* ac)
{
	kDebug() << "slotRemoveAction" ;
	QMenu* men = (QMenu*)ac->parentWidget();
	disconnect(men,0,0,0);
	QString serverName = men->title();


//	kpfMenu->removeAction(men);	
	kDebug() << "ServerName: "<< serverName ;

	WebServer* srv = webServerHash->value(serverName);		
	WebServerManager::instance()->disableServer(srv->root());
	webServerHash->remove(serverName);
	delete srv;
	kDebug() << "WebServerdeleted";	

	QList<QAction*> tmpList = actionHash->values(serverName);

	qDeleteAll(tmpList.begin(),tmpList.end());
	actionHash->remove(serverName);

	kDebug() << "Actions deleted ";
	men->clear();

	webServerMenuHash->remove(serverName);
	men->deleteLater();

}

void PlasmaKifer::slotPauseServerAction(QAction* ac)
{
	kDebug() << "slotPauseAction" ;
	QMenu* men = (QMenu*)ac->parentWidget();
	QString serverName = men->title();
	
	WebServer* srv = webServerHash->value(serverName);		
	srv->pause(!srv->paused());
	kDebug() << "Server is paused: " << srv->paused();

	if (srv->paused()) {
		men->setIcon(KIcon("user-offline"));
		pauseAction->setIcon(KIcon("media-playback-start"));
		pauseAction->setText("Start");
	} else {
		men->setIcon(KIcon("user-online"));
		pauseAction->setIcon(KIcon("media-playback-pause"));
		pauseAction->setText("Pause");
	}

	kDebug() << "ServerName: "<< serverName ;
}

void PlasmaKifer::slotRestartServerAction(QAction* ac)
{
	kDebug() << "slotRestartAction" ;
	QMenu* men = (QMenu*)ac->parentWidget();
	QString serverName = men->title();
	
	WebServer* srv = webServerHash->value(serverName);		
	srv->restart();
	kDebug() << "ServerName: "<< serverName ;
}

void PlasmaKifer::slotPrefsServerAction(QAction* ac)
{
	kDebug() << "slotPrefsAction" ;
	QMenu* men = (QMenu*)ac->parentWidget();
	QString serverName = men->title();
	
	WebServer* srv = webServerHash->value(serverName);		
	if (!configDialog) {
		configDialog = new SingleServerConfigDialog(srv, 0);
		connect(configDialog,SIGNAL(dying(SingleServerConfigDialog *)),SLOT(slotConfigDialogDying(SingleServerConfigDialog *)));
	}
	configDialog->show();
	kDebug() << "ServerName: "<< serverName ;
}

void PlasmaKifer::slotConfigDialogDying(SingleServerConfigDialog* dialog)
{
	dialog->delayedDestruct();
    	dialog = 0;
	configDialog = 0;
}

void PlasmaKifer::slotServerMenuTriggered(QAction* act)
{
	QHash<QString,QMenu*>::iterator foo;
	foo = webServerMenuHash->begin();
	for(foo = webServerMenuHash->begin(); foo != webServerMenuHash->end();foo++) {
		QMenu* tmp = foo.value();
		disconnect(tmp,SIGNAL(triggered(QAction*)),this,SLOT(slotServerMenuTriggered(QAction*)));
	}

	if (act->text() == "Monitor")
		slotMonitorAction(act);
	else if (act->text() == "Pause" || act->text() == "Start")
		slotPauseServerAction(act);	
	else if (act->text() == "Remove")
		slotRemoveServerAction(act);	
	else if (act->text() == "Restart")
		slotRestartServerAction(act);	
	else if (act->text() == "Preferences")	
		slotPrefsServerAction(act);

	for(foo = webServerMenuHash->begin(); foo != webServerMenuHash->end();foo++) {
		QMenu* tmp = foo.value();
		connect(tmp,SIGNAL(triggered(QAction*)),this,SLOT(slotServerMenuTriggered(QAction*)));
	}

}
#include "plasma-kifer.moc"
