/*******************************************************************************
***  This file is part of Dux Rei Nummariae.                                 ***
***                                                                          ***
***  Copyright (C) 2017, 2018, 2019, 2020, 2021                              ***
***  John Schneiderman <Licensing _AT_ Schneiderman _DOT_ me>                ***
***                                                                          ***
***  This program is free software: you can redistribute it and/or modify it ***
***  under the terms of the GNU Affero General Public License as published   ***
***  by the Free Software Foundation, either version 3 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 Affero General Public License for more details.             ***
***                                                                          ***
***  You should have received a copy of the GNU Affero General Public License***
***  along with this program. If not, see <http://www.gnu.org/licenses/>.    ***
*******************************************************************************/
#include <QObject>
using ::QObject;

#include <exception>
using std::exception;
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;

#include "Application.h"
using drn::desktop::Application;
#include <drn/config.h>
// using DuxReiNummariae_APPLICATION_LONG_NAME.
// using DuxReiNummariae_APPLICATION_SHORT_NAME.
// using DuxReiNummariae_FULL_VERSION.
// using DuxReiNummariae_COPYRIGHT_YEARS.
#include "desktop-ui/MainWindow.h"
using drn::desktop_ui::MainWindow;
#include <navigation/Navigator.h>
using drn::navigation::Navigator;


void establishConnections(Navigator& nav, MainWindow& mw)
{
	//{ Navigator -> Main Window Connections

	QObject::connect(
		&nav,
		&Navigator::showBills,
		&mw,
		&MainWindow::onShowBills
	);
	QObject::connect(
		&nav,
		&Navigator::showDebts,
		&mw,
		&MainWindow::onShowDebts
	);
	QObject::connect(
		&nav,
		&Navigator::showGoals,
		&mw,
		&MainWindow::onShowGoals
	);
	QObject::connect(
		&nav,
		&Navigator::showNontracks,
		&mw,
		&MainWindow::onShowNontracks
	);
	QObject::connect(
		&nav,
		&Navigator::showWages,
		&mw,
		&MainWindow::onShowWages
	);
	QObject::connect(
		&nav,
		&Navigator::saveSucceeded,
		&mw,
		&MainWindow::saveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::saveFailed,
		&mw,
		&MainWindow::saveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::showAccounts,
		&mw,
		&MainWindow::onShowAccounts
	);
	QObject::connect(
		&nav,
		&Navigator::accountSaveSucceeded,
		&mw,
		&MainWindow::accountSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::accountSaveFailed,
		&mw,
		&MainWindow::accountSaveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::showLedgers,
		&mw,
		&MainWindow::onShowLedgers
	);
	QObject::connect(
		&nav,
		&Navigator::showLedger,
		&mw,
		&MainWindow::showLedger
	);
	QObject::connect(
		&nav,
		&Navigator::transactionSaveSucceeded,
		&mw,
		&MainWindow::transactionSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::transactionSaveFailed,
		&mw,
		&MainWindow::transactionSaveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::showBanks,
		&mw,
		&MainWindow::onShowBanks
	);
	QObject::connect(
		&nav,
		&Navigator::bankSaveSucceeded,
		&mw,
		&MainWindow::bankSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::bankSaveFailed,
		&mw,
		&MainWindow::bankSaveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::bankAccountSaveSucceeded,
		&mw,
		&MainWindow::bankAccountSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::bankAccountSaveFailed,
		&mw,
		&MainWindow::bankAccountSaveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::showPostBudgetItems,
		&mw,
		&MainWindow::onShowPostBudgetItems
	);
	QObject::connect(
		&nav,
		&Navigator::lookedUpBankAccounts,
		&mw,
		&MainWindow::lookedUpBankAccounts
	);
	QObject::connect(
		&nav,
		&Navigator::lookedUpBudgetItemSources,
		&mw,
		&MainWindow::lookedUpBudgetItemSources
	);
	QObject::connect(
		&nav,
		&Navigator::postBudgetItemSaveSucceeded,
		&mw,
		&MainWindow::postBudgetItemSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::postBudgetItemSaveFailed,
		&mw,
		&MainWindow::postBudgetItemSaveFailed
	);
	QObject::connect(
		&nav,
		&Navigator::showConfirmNewBudgetFile,
		&mw,
		&MainWindow::onShowConfirmNewBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::clearedBudgetFile,
		&mw,
		&MainWindow::onClearedBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::showConfirmLoadBudgetFile,
		&mw,
		&MainWindow::onShowConfirmLoadBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::savedBudgetFile,
		&mw,
		&MainWindow::onSavedBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::loadedBudgetFile,
		&mw,
		&MainWindow::onLoadedBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::showSaveAsBudgetFile,
		&mw,
		&MainWindow::onShowSaveAsBudgetFile
	);
	QObject::connect(
		&nav,
		&Navigator::showNoBudgetFileOpened,
		&mw,
		&MainWindow::onShowNoBudgetFileOpened
	);
	QObject::connect(
		&nav,
		&Navigator::checkedIsBudgetFileDirty,
		&mw,
		&MainWindow::onCheckCleanExit
	);
	QObject::connect(
		&nav,
		&Navigator::showDashboard,
		&mw,
		&MainWindow::onShowDashboard
	);
	QObject::connect(
		&nav,
		&Navigator::showExchangeRates,
		&mw,
		&MainWindow::onShowExchangeRates
	);
	QObject::connect(
		&nav,
		&Navigator::fetchedExchangeRates,
		&mw,
		&MainWindow::fetchedExchangeRates
	);
	QObject::connect(
		&nav,
		&Navigator::showConfigure,
		&mw,
		&MainWindow::onShowConfigure
	);
	QObject::connect(
		&nav,
		&Navigator::configureSaveSucceeded,
		&mw,
		&MainWindow::configureSaveSucceeded
	);
	QObject::connect(
		&nav,
		&Navigator::configureSaveFailed,
		&mw,
		&MainWindow::configureSaveFailed
	);

	//}

	//{ Main Window -> Navigator Connections

	QObject::connect(
		&mw,
		&MainWindow::prepareShowBills,
		&nav,
		&Navigator::onPrepareShowBills
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowDebts,
		&nav,
		&Navigator::onPrepareShowDebts
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowGoals,
		&nav,
		&Navigator::onPrepareShowGoals
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowNontracks,
		&nav,
		&Navigator::onPrepareShowNontracks
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowWages,
		&nav,
		&Navigator::onPrepareShowWages
	);
	QObject::connect(
		&mw,
		&MainWindow::added,
		&nav,
		&Navigator::onAdded
	);
	QObject::connect(
		&mw,
		&MainWindow::renamed,
		&nav,
		&Navigator::onRenamed
	);
	QObject::connect(
		&mw,
		&MainWindow::updated,
		&nav,
		&Navigator::onUpdated
	);
	QObject::connect(
		&mw,
		&MainWindow::removed,
		&nav,
		&Navigator::onRemoved
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowAccounts,
		&nav,
		&Navigator::onPrepareShowAccounts
	);
	QObject::connect(
		&mw,
		&MainWindow::addedAct,
		&nav,
		&Navigator::onAddedAct
	);
	QObject::connect(
		&mw,
		&MainWindow::recoded,
		&nav,
		&Navigator::onRecoded
	);
	QObject::connect(
		&mw,
		&MainWindow::closed,
		&nav,
		&Navigator::onClosed
	);
	QObject::connect(
		&mw,
		&MainWindow::opened,
		&nav,
		&Navigator::onOpened
	);
	QObject::connect(
		&mw,
		&MainWindow::removedAct,
		&nav,
		&Navigator::onRemovedAct
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowLedgers,
		&nav,
		&Navigator::onPrepareShowLedgers
	);
	QObject::connect(
		&mw,
		&MainWindow::selectedLedger,
		&nav,
		&Navigator::onSelectedLedger
	);
	QObject::connect(
		&mw,
		&MainWindow::addedTransaction,
		&nav,
		&Navigator::onAddedTransaction
	);
	QObject::connect(
		&mw,
		&MainWindow::updatedTransaction,
		&nav,
		&Navigator::onUpdatedTransaction
	);
	QObject::connect(
		&mw,
		&MainWindow::markCleared,
		&nav,
		&Navigator::onMarkCleared
	);
	QObject::connect(
		&mw,
		&MainWindow::markReconciled,
		&nav,
		&Navigator::onMarkReconciled
	);
	QObject::connect(
		&mw,
		&MainWindow::removedTransaction,
		&nav,
		&Navigator::onRemovedTransaction
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowBanks,
		&nav,
		&Navigator::onPrepareShowBanks
	);
	QObject::connect(
		&mw,
		&MainWindow::bankAdded,
		&nav,
		&Navigator::onBankAdded
	);
	QObject::connect(
		&mw,
		&MainWindow::bankUpdated,
		&nav,
		&Navigator::onBankUpdated
	);
	QObject::connect(
		&mw,
		&MainWindow::bankRenamed,
		&nav,
		&Navigator::onBankRenamed
	);
	QObject::connect(
		&mw,
		&MainWindow::bankClosed,
		&nav,
		&Navigator::onBankClosed
	);
	QObject::connect(
		&mw,
		&MainWindow::bankOpened,
		&nav,
		&Navigator::onBankOpened
	);
	QObject::connect(
		&mw,
		&MainWindow::bankRemoved,
		&nav,
		&Navigator::onBankRemoved
	);
	QObject::connect(
		&mw,
		&MainWindow::addedBankAccount,
		&nav,
		&Navigator::onAddedBankAccount
	);
	QObject::connect(
		&mw,
		&MainWindow::renamedBankAccount,
		&nav,
		&Navigator::onRenamedBankAccount
	);
	QObject::connect(
		&mw,
		&MainWindow::removedBankAccount,
		&nav,
		&Navigator::onRemovedBankAccount
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowPostBudgetItems,
		&nav,
		&Navigator::onPrepareShowPostBudgetItems
	);
	QObject::connect(
		&mw,
		&MainWindow::lookUpBankAccounts,
		&nav,
		&Navigator::onLookUpBankAccounts
	);
	QObject::connect(
		&mw,
		&MainWindow::lookUpBudgetItemSources,
		&nav,
		&Navigator::onLookUpBudgetItemSources
	);
	QObject::connect(
		&mw,
		&MainWindow::postBudgetItemPosted,
		&nav,
		&Navigator::onPostBudgetItemPosted
	);
	QObject::connect(
		&mw,
		&MainWindow::postBudgetItemPostedUnexpected,
		&nav,
		&Navigator::onPostBudgetItemPostedUnexpected
	);
	QObject::connect(
		&mw,
		&MainWindow::postBudgetItemSkipped,
		&nav,
		&Navigator::onPostBudgetItemSkipped
	);
	QObject::connect(
		&mw,
		&MainWindow::newBudgetFile,
		&nav,
		&Navigator::onNewBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::confirmedNewBudgetFile,
		&nav,
		&Navigator::onConfirmedNewBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::loadBudgetFile,
		&nav,
		&Navigator::onLoadBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::confirmedLoadBudgetFile,
		&nav,
		&Navigator::onConfirmedLoadBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::saveBudgetFile,
		&nav,
		&Navigator::onSaveBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::saveAsBudgetFile,
		&nav,
		&Navigator::onSaveAsBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::reloadBudgetFile,
		&nav,
		&Navigator::onReloadBudgetFile
	);
	QObject::connect(
		&mw,
		&MainWindow::checkIsBudgetFileDirty,
		&nav,
		&Navigator::onCheckIsBudgetFileDirty
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowDashboard,
		&nav,
		&Navigator::onPrepareShowDashboard
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowExchangeRates,
		&nav,
		&Navigator::onPrepareShowExchangeRates
	);
	QObject::connect(
		&mw,
		&MainWindow::fetchExchangeRates,
		&nav,
		&Navigator::onFetchExchangeRates
	);
	QObject::connect(
		&mw,
		&MainWindow::storeExchangeRates,
		&nav,
		&Navigator::onStoreExchangeRates
	);
	QObject::connect(
		&mw,
		&MainWindow::prepareShowConfigure,
		&nav,
		&Navigator::onPrepareShowConfigure
	);
	QObject::connect(
		&mw,
		&MainWindow::configureUpdated,
		&nav,
		&Navigator::onConfigureUpdated
	);

	//}
}

int main(int argc, char* argv[])
try
{
	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	cout << DuxReiNummariae_APPLICATION_LONG_NAME << ' ' << DuxReiNummariae_FULL_VERSION << '\n'
		<< "Copyright (C) " << DuxReiNummariae_COPYRIGHT_YEARS << " John M. Schneiderman\n"
		<< DuxReiNummariae_APPLICATION_SHORT_NAME << " comes with ABSOLUTELY NO WARRANTY;\n"
		<< "This is free software, and you are welcome to redistribute it\n"
		<< "under certain conditions; see the LICENSE file for details,\n"
		<< "or the Free Software Foundation's AGPL.\n"
		<< endl;
	Application app{argc, argv};
	Navigator nav{};
	MainWindow mw{};
	establishConnections(nav, mw);
	mw.show();
	return app.exec();
}
catch (const exception& error)
{
	cerr << "An error occurred.\n" << error.what();
	return EXIT_FAILURE;
}
catch (...)
{
	cerr << "An unexpected error occurred.";
	return EXIT_FAILURE;
}
