/***************************************************************************
                          apollon.cpp -  description
                             -------------------
begin		: Dec 05 2003
copyright	: (C) 2002 by Bastiaan Naber, (C) 2002 by Robert Wittams
email		: bastiaan@ricardis.tudelft.nl
description	:

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>
#include <signal.h>

#include <dcopclient.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kconfig.h>
#include <kiconloader.h>
#include <kjanuswidget.h>
#include <kkeydialog.h>          //configShortcuts()
#include <klocale.h>
#include <kmenubar.h>
#include <kpopupmenu.h>
#include <kprocess.h>
#include <kstatusbar.h>
#include <kstdaccel.h>
#include <kstdaction.h>
#include <ktip.h>

#include <qapplication.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qvbox.h>

#include <libgift/libgift.h>
#include <libgift/conf.h>

#include "apollon.h"
#include "apolloninfotab.h"
#include "apollonplayertab.h"
#include "apollonsearchtab.h"
#include "apollonsharedviewtab.h"
#include "apollonchattab.h"
#include "apollonsystemtray.h"
#include "apollontransfertab.h"
#include "giftconnection.h"
#include "preferences.h"
#include "sigdialog.h"

ApollonApp::ApollonApp(QWidget *parent, const char *name) :
  DCOPObject("ApollonIface"),
  KMainWindow(parent, name),
  m_systemTray(0),
  m_shutdown(false),
  m_killGiFT(true),
  m_startDocked(false)
{
	QString  host;
	int      port;
	bool     remote;

	m_gcn = new giFTConnection();

	m_settingsDialog = new ApollonPreferencesDialog();
	m_sigDialog = new SigDialog(m_gcn);

	m_statsLabel = new QLabel(this);
	m_statsLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	m_statsLabel->setAlignment(AlignBottom | AlignRight);

	connect(m_gcn, SIGNAL(giftShareReply(QString)), this, SLOT(giftShareReply(QString)));
	connect(m_gcn, SIGNAL(sigGiFTPID(pid_t)),       this, SLOT(setGiFTpid(pid_t)));

	// Register with DCOP
	if(!kapp->dcopClient()->isRegistered())
	{
		kapp->dcopClient()->registerAs("apollon");
		kapp->dcopClient()->setDefaultObject(objId());
	}

	KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

	QString commandlineServer = args->getOption("s");

	if(!commandlineServer)
	{
		QString user(getenv("USER"));
		QString home(getenv("HOME"));
		QString filename(home);
		filename.append("/.giFT/ui/ui.conf");

		Config *config = config_new_ex((char *) filename.ascii(), false);

		host = config_get_str(config, (char *) "daemon/host");
		port = config_get_int(config, (char *) "daemon/port");
		remote = false;

		config_free(config);
	}
	else
	{
		QStringList PortHostList = QStringList::split(":", commandlineServer);
		host = PortHostList[0];
		port = PortHostList[1].toInt();
		remote = true;
	}

	if(args->isSet("d")) // apollon -d enables debug output
	{
		m_gcn->setDebugOutput(args->isSet("d")); // here you can add other objects which might have debug-output
	}

	m_gcn->setParams(host, port, remote);
	m_gcn->connectToServer();

	initStatusBar();
	initActions();
	initCentre();
	//initSysTray();  called by a slot now from a signal in the preferences

	statsUpdate(0, 0.0);

	readConfig();
}

bool ApollonApp::queryClose()
{
	if( m_shutdown || (m_systemTray == 0) )
	{
		return true;
	}

	hide();
	return false;
}

void ApollonApp::quit()
{
	qApp->quit();
	delete this;
}

ApollonApp::~ApollonApp()
{
	if(m_killGiFT)
	{
		// kill(giFT_pid, 9);
		system("killall giftd");
	}
}

void ApollonApp::initStatusBar()
{
	statusBar()->message(i18n("Connecting..."));
	m_statsLabel->setText("                      ");
	statusBar()->addWidget(m_statsLabel, 0, true);
}

void ApollonApp::statsUpdate(int activeDownloads, float rate)
{
	QString stats;
	if (activeDownloads > 1 || activeDownloads == 0)
		stats = QString::number(activeDownloads) + QString(i18n(" active downloads at %1 KB/s").arg(rate));
	else
		stats = i18n("1 active download at %1 KB/s").arg(rate);
	m_statsLabel->setText(stats);
}

void ApollonApp::readConfig()
{
	setAutoSaveSettings();
	m_settingsDialog->readConfig( true );
	m_uploadsEnabled = m_settingsDialog->uploadsCheck->isChecked();
	setAutoSaveSettings("MainWindow");
}

void ApollonApp::saveConfig()
{
	m_settingsDialog->saveConfig();
}

void ApollonApp::initActions()
{
	KActionCollection *ac = actionCollection();
	
	KAction *fileExitAction =        KStdAction::quit(                              this,             SLOT(quit()),       actionCollection(), "fileExitAction");
	KAction *settingsOptionsAction = KStdAction::preferences(                       m_settingsDialog, SLOT(exec()),       actionCollection(), "settingsOptionsAction");
	KAction *sigAddlinkAction =      new KAction(i18n("&Add Sig2Dat link"), "bookmark_add", 0, m_sigDialog, SLOT(exec()), actionCollection(), "sigAddlinkAction");

	// create File menu
	KPopupMenu *fileMenu = new KPopupMenu(this);
	sigAddlinkAction->plug(fileMenu);
	fileMenu->insertSeparator();
	fileExitAction->plug(fileMenu);

	// create Settings menu
	KPopupMenu *settingsMenu = new KPopupMenu(this);
	settingsOptionsAction->plug(settingsMenu);
	KStdAction::keyBindings(this, SLOT(configureShortcuts()), ac)->plug(settingsMenu);
	
	// assign Help menu
	KPopupMenu *helpMenu_ = helpMenu();

	// insert menus into the menubar
	menuBar()->insertItem(i18n("&File"),     fileMenu    );
	menuBar()->insertItem(i18n("S&ettings"), settingsMenu);
	menuBar()->insertItem(i18n("&Help"),     helpMenu_   );

	connect(m_settingsDialog, SIGNAL(ok()),              this,  SLOT(saveConfig()));
	connect(m_settingsDialog, SIGNAL(shutApollon(bool)), this,  SLOT(setShutdownApollon(bool)));
	connect(m_settingsDialog, SIGNAL(startDocked(bool)), this,  SLOT(setStartDocked(bool)));
	connect(m_settingsDialog, SIGNAL(showPopUps(int)),   this,  SLOT(setShowPopUps(int)));
	connect(m_settingsDialog, SIGNAL(startPage(int)),    this,  SLOT(setStartPage(int)));
	connect(m_settingsDialog, SIGNAL(restartDaemon()),   m_gcn, SLOT(restartDaemon()));
	connect(m_settingsDialog, SIGNAL(killDaemon(bool)),  this,  SLOT(setKillGiFT(bool)));
	connect(m_settingsDialog, SIGNAL(hideShares()),      this,  SLOT(sharesHide()));
	connect(m_settingsDialog, SIGNAL(showShares()),      this,  SLOT(sharesShow()));
        connect(m_settingsDialog, SIGNAL(dockingEnabled(bool)),      this,  SLOT(initSysTray(bool)));
	connect(m_settingsDialog, SIGNAL(progressBarType(int)),     this,  SLOT(setProgressBarType(int)));
}

void ApollonApp::initCentre()
{
	KIconLoader *loader = KGlobal::iconLoader();

	m_tabWidget = new KJanusWidget(this, "tabw", KJanusWidget::IconList);
	setCentralWidget(m_tabWidget);

	QVBox *infoBox   = m_tabWidget->addVBoxPage(i18n("Info"),           NULL, loader->loadIcon("messagebox_info", KIcon::Small, 32) );
	QVBox *searchBox = m_tabWidget->addVBoxPage(i18n("Search"),         NULL, loader->loadIcon("find",            KIcon::Small, 32));
	QVBox *transBox  = m_tabWidget->addVBoxPage(i18n("Transfers"),      NULL, loader->loadIcon("network",         KIcon::Small, 32) );
	QVBox *sharedBox = m_tabWidget->addVBoxPage(i18n("Shared folders"), NULL, loader->loadIcon("folder",          KIcon::Small,32));
	QVBox *playerBox = m_tabWidget->addVBoxPage(i18n("Player"),         NULL, loader->loadIcon("kmix",            KIcon::Small, 32));
	QVBox *chatBox = m_tabWidget->addVBoxPage(i18n("Chat"),     NULL, loader->loadIcon("package_toys",               KIcon::Small, 32));

	m_infoTab       = new ApollonInfoTab(      infoBox,   "ApollonInfoTab",     m_gcn);
	m_searchTab     = new ApollonSearchTab(    searchBox, "ApollonSearchTab",   m_gcn);
	m_transTab      = new ApollonTransferTab(  transBox,  "ApollonTransferTab", m_gcn);
	m_sharedViewTab = new ApollonSharedViewTab(sharedBox, "ApollonSharedViewTab");
	m_playerTab     = new ApollonPlayerTab(    playerBox, "ApollonPlayerTab",   m_tabWidget, 4);
	m_chatTab        = new ApollonChatTab(chatBox, "ApollonChatTab");

	m_transTab->setPreferences(m_settingsDialog);
	m_transTab->setPlayerTab(m_playerTab);
	m_sharedViewTab->setPlayerTab(m_playerTab);

	connect(m_settingsDialog, SIGNAL(autoSearchInterval(int)),       m_transTab,      SLOT(autoSearchInterval(int)));
	connect(m_settingsDialog, SIGNAL(sharedFolder(const QString &)), m_sharedViewTab, SLOT(addFolder(const QString &)));
	connect(m_infoTab,        SIGNAL(sigKill(bool)),                    this,            SLOT(setKillGiFT(bool)));
	connect(m_infoTab,        SIGNAL(statusMessage(QString)),        this,            SLOT(setStatus(QString)));
	connect(m_transTab,       SIGNAL(browseUser(QString)),           m_searchTab,     SLOT(browseUser(QString)));
	connect(m_transTab,       SIGNAL(browseUser(QString)),           this,            SLOT(showSearches(QString)));
	connect(m_transTab,       SIGNAL(statsUpdate(int, float)),       this,            SLOT(statsUpdate(int, float)));
	connect(m_sharedViewTab,  SIGNAL(syncShares()),                  this,            SLOT(sharesSync()));
	connect(m_transTab,       SIGNAL(sigSendHash(QString )), m_searchTab,     SLOT(slotGetHash(QString)));
	connect(m_transTab,       SIGNAL(sigDeleteHash(QString )), m_searchTab,     SLOT(slotDeleteHash(QString)));
}

void ApollonApp::setStatus(QString text)
{
	statusBar()->clear();
	statusBar()->message(text);
}

void ApollonApp::sharesSync()
{
	m_gcn->makeShareRequest("sync");
}

void ApollonApp::sharesHide()
{
	if(m_uploadsEnabled)
	{
		m_gcn->makeShareRequest("hide");
		m_uploadsEnabled = false;
	}
}

void ApollonApp::sharesShow()
{
	if(!m_uploadsEnabled)
	{
		m_gcn->makeShareRequest("show");
		m_uploadsEnabled = true;
	}
}

void ApollonApp::giftShareReply(QString reply)
{
	if(reply.find("status") > -1)
	{
		setStatus(i18n("Synchronizing shares: ") + giFTConnection::searchKey("status", reply));

		if(reply.find("Done") > -1)
		{
			m_gcn->makeStatsRequest();
		}
	}
	else
	{
		if(reply.find("hide") > -1)
		{
			setStatus(i18n("Shares are now hidden."));
			m_gcn->makeStatsRequest();
		}
		else
		{
			setStatus(i18n("Shares are now shown."));
			m_gcn->makeStatsRequest();
		}
	}
}

void ApollonApp::showSearches(QString)
{
	m_tabWidget->showPage(1);
}

void ApollonApp::initSysTray(bool docking)
{
	if (docking)
	{
		if ( m_systemTray == 0 )
		{
			m_systemTray = new ApollonSystemTray(this, "systemTray");
			m_systemTray->show();
			m_transTab->setTray(m_systemTray);
			m_chatTab->setTray(m_systemTray);
			connect(m_systemTray, SIGNAL(quitSelected()),          this,         SLOT(quit()));
			connect(m_transTab,   SIGNAL(statsUpdate(int, float)), m_systemTray, SLOT(statsUpdate(int, float)));
		}
	}
	else
	{
		if (m_systemTray)
		{
			disconnect(m_systemTray, SIGNAL(quitSelected()),          this,         SLOT(quit()));
			disconnect(m_transTab,   SIGNAL(statsUpdate(int, float)), m_systemTray, SLOT(statsUpdate(int, float)));
			delete m_systemTray;
		}
		m_systemTray = 0;
		m_transTab->setTray(m_systemTray);
		m_chatTab->setTray(m_systemTray);
	}
}

void ApollonApp::setGiFTpid(pid_t pid)
{
	m_giFTpid = pid;
}

void ApollonApp::setKillGiFT(bool killGiFT)
{
	m_killGiFT = killGiFT;
}

void ApollonApp::setShowPopUps(int show)
{
	m_transTab->setShowPopup(show);
	m_chatTab->setShowPopup(show);
}

void ApollonApp::setStartPage(int page)
{
	m_tabWidget->showPage(page);
}

void ApollonApp::setProgressBarType(int type)
{
	m_transTab->setProgressBarType(type);
}

void ApollonApp::configureShortcuts() //SLOT
{
	KKeyDialog::configure( actionCollection(), this );
}

void ApollonApp::safePlug( KActionCollection *ac, const char *name, QWidget *w )
{
	if( ac )
	{
		KAction *a = ac->action( name );
		if( a )
			a->plug( w );
		else
			kdWarning() << k_funcinfo << "Action == NULL!\n";
			
	}
	else
		kdWarning() << k_funcinfo << "ActionCollection == NULL!\n";
}



#include "apollon.moc"

