#include "stdafx.h"
#include "version.h"
#include "mainwindow.h"
#include <QtWidgets/QApplication>

/*!
\mainpage
VoxelBlur is an interactive 3D volume rendering program, featuring an interactive depth-of-field effect. 
\section about About
This application was created by Florian Schaukowitsch as a lab exercise during the course 
<a href="http://www.cg.tuwien.ac.at/courses/Visualisierung2/index.html">Visualisierung 2</a> (Visualization 2) 
at the <a href="http://www.tuwien.ac.at"> Vienna University of Technology</a>.
For more information about the application, including the complete source code and binaries, <a href="../index.html">see the main page here</a>.
*/

/*!
\file
Contains the entry point of the application.
*/


QMutex logMutex;
QtMessageHandler defaultHandler;
QTextStream* logStream;
void vbMessageHandlerInit()
{
	QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
	QDir dir(path);
	if(!dir.exists())
		dir.mkpath(path);

	QString filepath = dir.filePath("app.log");
	qDebug()<<"Using logfile: "<<filepath;
	//using qApp as parent should flush and close the file automatically 
	QFile* logFile = new QFile(filepath,qApp);

	bool ok = logFile->open(QFile::WriteOnly | QFile::Truncate);
	if(!ok)
	{
		qCritical()<<"Could not create logging file '"<<filepath<<"'. Error: "<<logFile->errorString();
		logFile->close();
		logFile = nullptr;
		logStream = nullptr;
	}
	else
	{
		logStream = new QTextStream(logFile);
		//write a simple header
		*logStream<<"VoxelBlur logging started on "<<QDateTime::currentDateTime().toString(Qt::ISODate)<<endl;
	}
}

void vbMessageHandlerDestroy()
{
	//file is closed automatically by qApp
	SafeDelete(logStream); //this also flushes
}

const QString getMessage(QtMsgType type, const QMessageLogContext& ctx,const QString& msg)
{
	//shamelessly modeled after the internal qt function qMessageFormatString
	//it would be much nicer if this method were exposed...

	QString message;
	message.append(QTime::currentTime().toString());
	message.append(" [");
	switch (type) {
	case QtDebugMsg: message.append("debug"); break;
	case QtWarningMsg: message.append("warning"); break;
	case QtCriticalMsg:message.append("critical"); break;
	case QtFatalMsg: message.append("fatal"); break;
	}
	message.append(']');
	if (ctx.file)
	{
		message.append('[');
		//message.append(ctx.function);
		//if (ctx.file)
		{
			//message.append(':');
			message.append(ctx.file);
			message.append(':');
			message.append(QString::number(ctx.line));
		}
		message.append(']');
	}
	message.append(' ');
	message.append(msg);

	return message;
}

void vbMessageHandler(QtMsgType type, const QMessageLogContext& ctx,const QString& msg)
{
	if(logStream)
	{
		//make this thread safe, the default handler already is
		QMutexLocker locker(&logMutex);
		*logStream<<getMessage(type,ctx,msg)<<endl;
	}
	//also let qt do its magic
	defaultHandler(type,ctx,msg);
}

/*!
Entry point of the application. Sets up Qt, opens the MainWindow and then runs the Qt event loop until the app closes.
*/
int main(int argc, char *argv[])
{
	//setup application
	QApplication a(argc, argv);
	a.setApplicationName(VER_PRODUCTNAME_STR);
	a.setApplicationVersion(VER_PRODUCTVERSION_STR);
	a.setOrganizationName(VER_COMPANYNAME_STR);

	qSetMessagePattern("[%{type}][%{function}] %{message}");
	vbMessageHandlerInit();
	defaultHandler = qInstallMessageHandler(vbMessageHandler);

	//setup main window
	MainWindow w;
	w.show();

	//kick off loop, remain here until program end
	qDebug()<<"Starting event loop";
	int val = a.exec();
	vbMessageHandlerDestroy();
	return val;
}
