/***************************************************************************
 *   Copyright (C) 2010 by Volker Lanz <vl@fidra.de>                       *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

#include "core/storage.h"

#include "veneer/system.h"

#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QFile>
#include <QDebug>
#include <QProcess>
#include <QDir>
#include <QVariant>

static const char initSqlName[] = "init.sql";
static const char databaseFileName[] = "workout.db";

bool Storage::open(const QString& name)
{
	QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", name);

	QString databaseFilePath = Veneer::findFilePath(databaseFileName);

	// we might have to create an empty database, so make sure the path exists
	QString databaseDir = QFileInfo(databaseFilePath).absolutePath();
	if (!QDir(databaseDir).exists())
	{
		if (!QDir().mkpath(databaseDir))
		{
			qWarning() << "Could not create directory " << databaseDir << " for database file.";
			return false;
		}

// 		qDebug() << "created directory " << databaseDir << " for database file " << databaseFileName;
	}
// 	else
// 		qDebug() << "database dir " << databaseDir << " exists.";

	db.setDatabaseName(databaseFilePath);

	if (!db.open())
	{
		qWarning() << "Could not open database: " << db.lastError();
		return false;
	}

	return true;
}

bool Storage::init()
{
	if (!open())
		return false;

	QSqlDatabase db = QSqlDatabase::database();

	QSqlQuery query;
	if (!query.exec("SELECT name FROM sqlite_master WHERE type='table' AND name='profile'"))
	{
		qWarning() << "Could not execute a simple SQL statement on the database: " << query.lastError();
		return false;
	}

	if (!query.next())
	{
		query.clear();

		QFile scriptFile(Veneer::findExistingFilePath(initSqlName));

		if (!scriptFile.open(QFile::ReadOnly))
		{
			qWarning() << "Could not open script file " << scriptFile.fileName() << " to initialize the database.";
			return false;
		}

		QString script;
		QString line;

		db.transaction();

		while (!(line = scriptFile.readLine()).isEmpty())
		{
			line = line.simplified();

			if (line.isEmpty() || line.startsWith('-'))
				continue;

			script += ' ' + line;
		}

		const QStringList sql = script.split(';', QString::SkipEmptyParts);
		bool scriptCreateOk = true;

		for (int i = 0; i < sql.count() && scriptCreateOk; i++)
		{
			const QString command = sql[i].simplified();

			if (command.isEmpty())
				continue;

			scriptCreateOk = query.exec(command);
// 			qDebug() << "run query: " << command << ", result: " << scriptCreateOk;
		}

		if (!scriptCreateOk)
		{
			db.rollback();
			qWarning() << "Failed to run the script file to setup the database: " << query.lastError();
			return false;
		}

		db.commit();
	}

	if (!query.exec("PRAGMA foreign_keys = 1") || !query.exec("PRAGMA foreign_keys") || !query.next())
	{
		qWarning() << "Could not set or query foreign keys support for the database: " << query.lastError() << " -- Make sure the sqlite version you have installed is 3.6.19 or newer.";
		return false;
	}

	return true;
}
