/*********
*
* This file is part of BibleTime's source code, http://www.bibletime.info/.
*
* Copyright 1999-2006 by the BibleTime developers.
* The BibleTime source code is licensed under the GNU General Public License version 2.0.
*
**********/



//BibleTime includes
#include "bibletime.h"

#include "backend/btstringmgr.h"
#include "backend/cswordbackend.h"

#include "frontend/mainindex/cmainindex.h"
#include "frontend/cprofilemgr.h"
#include "frontend/cprofile.h"
#include "frontend/cmdiarea.h"
#include "frontend/kstartuplogo.h"
#include "frontend/cswordsetupdialog.h"
#include "frontend/cprinter.h"
#include "frontend/cmanageindiceswidget.h"

#include "backend/clanguagemgr.h"


#include "config.h"
#include "frontend/cbtconfig.h"
#include "frontend/cinfodisplay.h"

#include "util/cpointers.h"
#include "util/cresmgr.h"

//system includes
#include <stdlib.h>

//TQt includes
#include <tqpopupmenu.h>
#include <tqsplitter.h>
#include <tqguardedptr.h>
#include <tqlistview.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqvbox.h>

//TDE includes
#include <tdeaboutdata.h>
#include <tdeaccel.h>
#include <tdeaction.h>
#include <tdeapplication.h>
#include <tdeconfigbase.h>
#include <tdeglobal.h>
#include <khelpmenu.h>
#include <kiconloader.h>
#include <tdemenubar.h>
#include <tdestandarddirs.h>
#include <kstdaction.h>
#include <tdetoolbar.h>
#include <tdelocale.h>
#include <tdepopupmenu.h>

//Sword includes
#include <swlog.h>

using namespace InfoDisplay;
using namespace Profile;

/**Initializes the view of this widget*/
void BibleTime::initView() {
	TDEStartupLogo::setStatusMessage(i18n("Creating BibleTime's GUI") + TQString("..."));

	m_mainSplitter = new TQSplitter(this, "mainsplitter");
	m_mainSplitter->setChildrenCollapsible(false);
	setCentralWidget(m_mainSplitter);

	m_leftPaneSplitter = new TQSplitter(TQt::Vertical, m_mainSplitter);
	m_leftPaneSplitter->setChildrenCollapsible(false);
	
	TQVBox* vBox = new TQVBox(m_leftPaneSplitter);
	vBox->setMinimumSize(100, 100);
	
	TQLabel* bookshelfLabel = new TQLabel( i18n("Bookshelf"), vBox );
	bookshelfLabel->setMargin(5);

	m_mainIndex = new CMainIndex(vBox);

	m_infoDisplay = new CInfoDisplay(m_leftPaneSplitter);
	CPointers::setInfoDisplay(m_infoDisplay);

	m_mdi = new CMDIArea(m_mainSplitter, "mdiarea" );
	m_mdi->setMinimumSize(100, 100);
	m_mdi->setFocusPolicy(TQWidget::ClickFocus);

	m_helpMenu = new KHelpMenu(this, TDEGlobal::instance()->aboutData(), true, actionCollection());
}

/** Initializes the action objects of the GUI */
void BibleTime::initActions() {
	TDEStartupLogo::setStatusMessage(i18n("Initializing menu- and toolbars") + TQString("..."));
	TDEAction* action = 0;

	action = KStdAction::quit(tdeApp, TQ_SLOT( quit() ), actionCollection());
	action->setToolTip( CResMgr::mainMenu::file::quit::tooltip );

	action = new TDEAction(i18n("Search in &open work(s)"),
						 CResMgr::mainMenu::mainIndex::search::icon,
						 CResMgr::mainMenu::mainIndex::search::accel,
						 this, TQ_SLOT(slotSearchModules()), actionCollection(),
						 CResMgr::mainMenu::mainIndex::search::actionName
						);
	action->setToolTip( CResMgr::mainMenu::mainIndex::search::tooltip );

	action = new TDEAction(i18n("Search in standard &Bible"),
						 CResMgr::mainMenu::mainIndex::searchdefaultbible::icon,
						 CResMgr::mainMenu::mainIndex::searchdefaultbible::accel,
						 this, TQ_SLOT(slotSearchDefaultBible()), actionCollection(),
						 CResMgr::mainMenu::mainIndex::searchdefaultbible::actionName
						);
	action->setToolTip( CResMgr::mainMenu::mainIndex::searchdefaultbible::tooltip );

	m_viewToolbar_action = KStdAction::showToolbar(this, TQ_SLOT( slotToggleToolbar() ), actionCollection());
	m_viewToolbar_action->setToolTip( CResMgr::mainMenu::view::showToolBar::tooltip );

	m_viewMainIndex_action = new TDEToggleAction(i18n("&Show bookshelf"),
							 CResMgr::mainMenu::view::showMainIndex::icon,
							 CResMgr::mainMenu::view::showMainIndex::accel,
							 this, TQ_SLOT(slotToggleMainIndex()), actionCollection(),
							 CResMgr::mainMenu::view::showMainIndex::actionName);
	m_viewMainIndex_action->setToolTip( CResMgr::mainMenu::view::showMainIndex::tooltip );

	m_viewInfoDisplay_action = new TDEToggleAction(i18n("Show &mag"),
							   CResMgr::mainMenu::view::showInfoDisplay::icon,
							   CResMgr::mainMenu::view::showInfoDisplay::accel,
							   this, TQ_SLOT(slotToggleInfoDisplay()), actionCollection(),
							   CResMgr::mainMenu::view::showInfoDisplay::actionName);
	m_viewMainIndex_action->setToolTip( CResMgr::mainMenu::view::showInfoDisplay::tooltip );

	action = KStdAction::preferences(this, TQ_SLOT( slotSettingsOptions() ), actionCollection());
	action->setToolTip( CResMgr::mainMenu::settings::optionsDialog::tooltip );

	action = new TDEAction(i18n("Bookshelf &Manager"),
						 CResMgr::mainMenu::settings::swordSetupDialog::icon,
						 CResMgr::mainMenu::settings::swordSetupDialog::accel,
						 this, TQ_SLOT( slotSwordSetupDialog() ), actionCollection(),
						 CResMgr::mainMenu::settings::swordSetupDialog::actionName
						);
	action->setToolTip( CResMgr::mainMenu::settings::swordSetupDialog::tooltip );
	//delete help action if TDE created it
	if ( actionCollection()->action( KStdAction::stdName(KStdAction::ConfigureToolbars) )) {
		actionCollection()->remove
		(actionCollection()->action(
			 KStdAction::stdName(KStdAction::ConfigureToolbars))
		);
	}
	action = KStdAction::configureToolbars(this, TQ_SLOT( slotSettingsToolbar() ), actionCollection());
	action->setToolTip( CResMgr::mainMenu::settings::editToolBar::tooltip );
	m_windowArrangementMode_action = new TDEActionMenu(i18n("&Arrangement mode"),
							 CResMgr::mainMenu::window::arrangementMode::icon,
							 actionCollection(),
							 CResMgr::mainMenu::window::arrangementMode::actionName);
	m_windowArrangementMode_action->setDelayed( false );

	m_windowManualMode_action = new TDEToggleAction(i18n("&Manual mode"),
								CResMgr::mainMenu::window::arrangementMode::manual::icon,
								CResMgr::mainMenu::window::arrangementMode::manual::accel,
								this, TQ_SLOT(slotManualArrangementMode()), actionCollection(),
								CResMgr::mainMenu::window::arrangementMode::manual::actionName
												 );
	m_windowManualMode_action->setToolTip(
		CResMgr::mainMenu::window::arrangementMode::manual::tooltip
	);
	m_windowArrangementMode_action->insert( m_windowManualMode_action );


	m_windowAutoTileVertical_action = new TDEToggleAction(i18n("Auto-tile &vertically"),
									  CResMgr::mainMenu::window::arrangementMode::autoTileVertical::icon,
									  CResMgr::mainMenu::window::arrangementMode::autoTileVertical::accel,
									  this, TQ_SLOT(slotAutoTileVertical()), actionCollection(),
									  CResMgr::mainMenu::window::arrangementMode::autoTileVertical::actionName
													   );
	m_windowAutoTileVertical_action->setToolTip(
		CResMgr::mainMenu::window::arrangementMode::autoTileVertical::tooltip
	);
	m_windowArrangementMode_action->insert( m_windowAutoTileVertical_action );


	m_windowAutoTileHorizontal_action = new TDEToggleAction(i18n("Auto-tile &horizontally"),
										CResMgr::mainMenu::window::arrangementMode::autoTileHorizontal::icon,
										CResMgr::mainMenu::window::arrangementMode::autoTileHorizontal::accel,
										this, TQ_SLOT(slotAutoTileHorizontal()), actionCollection(),
										CResMgr::mainMenu::window::arrangementMode::autoTileHorizontal::actionName
														 );
	m_windowAutoTileHorizontal_action->setToolTip(
		CResMgr::mainMenu::window::arrangementMode::autoTileHorizontal::tooltip
	);
	m_windowArrangementMode_action->insert( m_windowAutoTileHorizontal_action );


	m_windowAutoCascade_action  = new TDEToggleAction(i18n("Auto-&cascade"),
								  CResMgr::mainMenu::window::arrangementMode::autoCascade::icon,
								  CResMgr::mainMenu::window::arrangementMode::autoCascade::accel,
								  this, TQ_SLOT(slotAutoCascade()), actionCollection(),
								  CResMgr::mainMenu::window::arrangementMode::autoCascade::actionName
												   );
	m_windowAutoCascade_action->setToolTip(
		CResMgr::mainMenu::window::arrangementMode::autoCascade::tooltip
	);
	m_windowArrangementMode_action->insert( m_windowAutoCascade_action );

	m_windowCascade_action = new TDEAction(i18n("&Cascade"),
										 CResMgr::mainMenu::window::cascade::icon,
										 CResMgr::mainMenu::window::cascade::accel,
										 this, TQ_SLOT(slotCascade()), actionCollection(),
										 CResMgr::mainMenu::window::cascade::actionName
										);
	m_windowCascade_action->setToolTip( CResMgr::mainMenu::window::cascade::tooltip );

	m_windowTileVertical_action = new TDEAction(i18n("Tile &vertically"),
								  CResMgr::mainMenu::window::tileVertical::icon,
								  CResMgr::mainMenu::window::tileVertical::accel,
								  this, TQ_SLOT(slotTileVertical()), actionCollection(),
								  CResMgr::mainMenu::window::tileVertical::actionName
											 );
	m_windowTileVertical_action->setToolTip( CResMgr::mainMenu::window::tileVertical::tooltip );
	m_windowTileHorizontal_action = new TDEAction(i18n("Tile &horizontally"),
									CResMgr::mainMenu::window::tileHorizontal::icon,
									CResMgr::mainMenu::window::tileHorizontal::accel,
									this, TQ_SLOT(slotTileHorizontal()), actionCollection(),
									CResMgr::mainMenu::window::tileHorizontal::actionName
											   );
	m_windowTileHorizontal_action->setToolTip( CResMgr::mainMenu::window::tileHorizontal::tooltip );

	m_windowCloseAll_action = new TDEAction(i18n("Cl&ose all"),
										  CResMgr::mainMenu::window::closeAll::icon,
										  CResMgr::mainMenu::window::closeAll::accel,
										  m_mdi, TQ_SLOT(deleteAll()), actionCollection(),
										  CResMgr::mainMenu::window::closeAll::actionName
										 );
	m_windowCloseAll_action->setToolTip( CResMgr::mainMenu::window::closeAll::tooltip );

	m_windowSaveProfile_action = new TDEActionMenu(i18n("&Save session"),
								 CResMgr::mainMenu::window::saveProfile::icon,
								 actionCollection(),
								 CResMgr::mainMenu::window::saveProfile::actionName
												);
	m_windowSaveProfile_action->setToolTip( CResMgr::mainMenu::window::saveProfile::tooltip );
	m_windowSaveProfile_action->setDelayed( false );

	m_windowSaveToNewProfile_action = new TDEAction(i18n("Save as &new session"),
									  CResMgr::mainMenu::window::saveToNewProfile::icon,
									  CResMgr::mainMenu::window::saveToNewProfile::accel,
									  this, TQ_SLOT(saveToNewProfile()), actionCollection(),
									  CResMgr::mainMenu::window::saveToNewProfile::actionName
												 );
	m_windowSaveToNewProfile_action->setToolTip( CResMgr::mainMenu::window::saveToNewProfile::tooltip );

	m_windowLoadProfile_action = new TDEActionMenu(i18n("&Load session"),
								 CResMgr::mainMenu::window::loadProfile::icon,
								 actionCollection(),
								 CResMgr::mainMenu::window::loadProfile::actionName
												);
	m_windowLoadProfile_action->setToolTip(	CResMgr::mainMenu::window::loadProfile::tooltip	);
	m_windowLoadProfile_action->setDelayed( false );
	m_windowDeleteProfile_action = new TDEActionMenu(i18n("&Delete session"),
								   CResMgr::mainMenu::window::deleteProfile::icon,
								   actionCollection(),
								   CResMgr::mainMenu::window::deleteProfile::actionName
												  );
	m_windowLoadProfile_action->setToolTip( CResMgr::mainMenu::window::deleteProfile::tooltip );
	m_windowLoadProfile_action->setDelayed( false );
	m_windowFullscreen_action = new TDEToggleAction(i18n("&Fullscreen mode"),
								CResMgr::mainMenu::window::showFullscreen::icon,
								CResMgr::mainMenu::window::showFullscreen::accel,
								this, TQ_SLOT(toggleFullscreen()), actionCollection(),
								CResMgr::mainMenu::window::showFullscreen::actionName
												 );
	m_windowFullscreen_action->setToolTip( CResMgr::mainMenu::window::showFullscreen::tooltip );
	m_windowFullscreen_action->setShortcutConfigurable(true);

	//connect the profile popups to the right slots
	TDEPopupMenu* loadPopup = m_windowLoadProfile_action->popupMenu();
	TDEPopupMenu* savePopup = m_windowSaveProfile_action->popupMenu();
	TDEPopupMenu* deletePopup = m_windowDeleteProfile_action->popupMenu();

	connect(loadPopup, TQ_SIGNAL(activated(int)), TQ_SLOT(loadProfile(int)));
	connect(savePopup, TQ_SIGNAL(activated(int)), TQ_SLOT(saveProfile(int)));
	connect(deletePopup, TQ_SIGNAL(activated(int)), TQ_SLOT(deleteProfile(int)));

	refreshProfileMenus();

	if ( actionCollection()->action( KStdAction::stdName(KStdAction::HelpContents) )) {  //delete help action if TDE created it
		actionCollection()->remove
		(actionCollection()->action(KStdAction::stdName(KStdAction::HelpContents)) );
	}

	action = new TDEAction(i18n("&Handbook"),
						 CResMgr::mainMenu::help::handbook::icon,
						 CResMgr::mainMenu::help::handbook::accel,
						 this, TQ_SLOT(openOnlineHelp_Handbook()), actionCollection(),
						 CResMgr::mainMenu::help::handbook::actionName
						);
	action->setToolTip( CResMgr::mainMenu::help::handbook::tooltip );

	action = new TDEAction(i18n("&Bible Study Howto"),
						 CResMgr::mainMenu::help::bibleStudyHowTo::icon,
						 CResMgr::mainMenu::help::bibleStudyHowTo::accel,
						 this, TQ_SLOT(openOnlineHelp_Howto()), actionCollection(),
						 CResMgr::mainMenu::help::bibleStudyHowTo::actionName
						);
	action->setToolTip( CResMgr::mainMenu::help::bibleStudyHowTo::tooltip );

	if ( actionCollection()->action( KStdAction::stdName( KStdAction::WhatsThis ) ) ) {  //delete "What's this" action if TDE created it already
		TDEAction* action = actionCollection()->action(KStdAction::stdName( KStdAction::WhatsThis ));
		actionCollection()->remove
		( action );
	}


	if ( actionCollection()->action( KStdAction::stdName( KStdAction::ReportBug ) ) ) { //delete Report Bug action if TDE created it
		actionCollection()->remove
		(actionCollection()->action(KStdAction::stdName( KStdAction::ReportBug )));
	}
	action = KStdAction::reportBug(m_helpMenu, TQ_SLOT(reportBug()), actionCollection());
	action->setToolTip(CResMgr::mainMenu::help::bugreport::tooltip);
	action = new TDEAction(i18n("&Daily tip"),
						 CResMgr::mainMenu::help::dailyTip::icon,
						 CResMgr::mainMenu::help::dailyTip::accel,
						 this, TQ_SLOT(slotHelpTipOfDay()), actionCollection(),
						 CResMgr::mainMenu::help::dailyTip::actionName
						);
	action->setToolTip(CResMgr::mainMenu::help::dailyTip::tooltip);
	if ( actionCollection()->action( KStdAction::stdName( KStdAction::AboutApp ) ) ) {  //delete About TDE action if TDE created it
		actionCollection()->remove
		(actionCollection()->action(KStdAction::stdName( KStdAction::AboutApp )));
	}
	action = KStdAction::aboutApp(m_helpMenu, TQ_SLOT(aboutApplication()), actionCollection());
	action->setToolTip(CResMgr::mainMenu::help::aboutBibleTime::tooltip);

	//delete About TDE action if TDE created it already
	if ( actionCollection()->action( KStdAction::stdName( KStdAction::AboutKDE ) ) ) {  //delete About TDE action if TDE created it
		actionCollection()->remove
		(actionCollection()->action(KStdAction::stdName( KStdAction::AboutKDE )));
	}
	action = KStdAction::aboutKDE(m_helpMenu, TQ_SLOT(aboutKDE()), actionCollection());
	action->setToolTip(CResMgr::mainMenu::help::aboutKDE::tooltip);
}

/** Initializes the menubar of BibleTime. */
void BibleTime::initMenubar() {
	//get the window and edit menus using the actions and their properties
	m_windowMenu = dynamic_cast<TQPopupMenu*>(m_windowCloseAll_action->container(0));
}

/** Initializes the signal / slot connections */
void BibleTime::initConnections() {
	connect(m_mdi, TQ_SIGNAL(sigSetToplevelCaption(const TQString&)),
			this, TQ_SLOT(setPlainCaption(const TQString&)));
	connect(m_mdi, TQ_SIGNAL(createReadDisplayWindow(ListCSwordModuleInfo, const TQString&)),
			this, TQ_SLOT(createReadDisplayWindow(ListCSwordModuleInfo, const TQString&)));

	Q_ASSERT(m_windowMenu);
	if (m_windowMenu) {
		connect(m_windowMenu, TQ_SIGNAL(aboutToShow()),
				this, TQ_SLOT(slotWindowMenuAboutToShow()));
	}
	else {
		tqWarning("Main window: can't find window menu");
	}


	connect(
		m_mainIndex, TQ_SIGNAL(createReadDisplayWindow(ListCSwordModuleInfo, const TQString&)),
		this, TQ_SLOT(createReadDisplayWindow(ListCSwordModuleInfo,const TQString&))
	);
	connect(
		m_mainIndex, TQ_SIGNAL(createWriteDisplayWindow(CSwordModuleInfo*, const TQString&, const CDisplayWindow::WriteWindowType&)),
		this, TQ_SLOT(createWriteDisplayWindow(CSwordModuleInfo*,const TQString&, const CDisplayWindow::WriteWindowType&))
	);
	connect(m_mainIndex, TQ_SIGNAL(signalSwordSetupChanged()), this, TQ_SLOT(slotSwordSetupChanged()));
}

/** Initializes the backend */
void BibleTime::initBackends() {
	TDEStartupLogo::setStatusMessage(i18n("Initializing Sword") + TQString("..."));

	StringMgr::setSystemStringMgr( new BTStringMgr() );
	SWLog::getSystemLog()->setLogLevel(1);

	m_backend = new CSwordBackend();
	m_backend->booknameLanguage( CBTConfig::get
									 (CBTConfig::language) );

	CPointers::setBackend(m_backend);
	const CSwordBackend::LoadError errorCode = m_backend->initModules();

	m_moduleList = 0;
	if ( errorCode == CSwordBackend::NoError ) { //no error
		m_moduleList = &(m_backend->moduleList());
	}
	else {
		m_moduleList = 0;
		//show error message that initBackend failed
		switch (errorCode) {
			case CSwordBackend::NoSwordConfig: //mods.d or mods.conf missing
			{
				TDEStartupLogo::hideSplash();
				BookshelfManager::CSwordSetupDialog dlg;
				dlg.showPart( BookshelfManager::CSwordSetupDialog::Sword );
				dlg.exec();
				break;
			}

			case CSwordBackend::NoModules: //no modules installed, but config exists
			{
				TDEStartupLogo::hideSplash();
				BookshelfManager::CSwordSetupDialog dlg;
				dlg.showPart( BookshelfManager::CSwordSetupDialog::Install );
				dlg.exec();
				break;
			}

			default: //unknown error
			{
				TDEStartupLogo::hideSplash();
				BookshelfManager::CSwordSetupDialog dlg;
				dlg.showPart( BookshelfManager::CSwordSetupDialog::Sword );
				dlg.exec();
				break;
			}
		}
	}

	TDEStartupLogo::setStatusMessage(i18n("Checking indices") + TQString("..."));
	//This function will 
	// - delete all orphaned indexes (no module present) if autoDeleteOrphanedIndices is true
	// - delete all indices of modules where hasIndex() returns false
	BookshelfManager::CManageIndicesWidget::deleteOrphanedIndices();
	
}

/** Apply the settings given by the profile p*/
void BibleTime::applyProfileSettings( CProfile* p ) {
	Q_ASSERT(p);
	if (!p) return;

	if (m_initialized) { //on startup TDE sets the main geometry
		//see polish(), where m_initialized is set and the TDE methods are called for window resize
		
		//first Main Window state
		m_windowFullscreen_action->setChecked( p->fullscreen() );  //set the fullscreen button state
		toggleFullscreen(); //either showFullscreen or showNormal
		if (p->maximized()) TDEMainWindow::showMaximized(); //if maximized, then also call showMaximized
	
		//Then Main Window geometry
		TDEMainWindow::resize( p->geometry().size() ); //Don't use TDEMainWindowInterface::resize
		TDEMainWindow::move( p->geometry().topLeft() );//Don't use TDEMainWindowInterface::move
}
}

/** Stores the settings of the mainwindow in the profile p */
void BibleTime::storeProfileSettings( CProfile* p ) {
	Q_ASSERT(p && m_windowFullscreen_action);
	if (!p || !m_windowFullscreen_action) return;
	
	p->setFullscreen( m_windowFullscreen_action->isChecked() );
	p->setMaximized( this->TDEMainWindow::isMaximized() );

	TQRect geometry;
	geometry.setTopLeft(pos());
	geometry.setSize(size());
	p->setGeometry(geometry);
}
