/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "sqlstoragebackend.h"
#include <QDir>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QtDebug>
#include <util/db/dblock.h>

using namespace LeechCraft;

SQLStorageBackend::SQLStorageBackend ()
: DB_ (QSqlDatabase::addDatabase ("QSQLITE", "CoreConnection"))
{
	QDir dir = QDir::home ();
	dir.cd (".leechcraft");
	dir.cd ("core");
	DB_.setDatabaseName (dir.filePath ("core.db"));
	if (!DB_.open ())
		LeechCraft::Util::DBLock::DumpError (DB_.lastError ());

	if (!DB_.tables ().contains ("sitesAuth"))
		InitializeTables ();
}

SQLStorageBackend::~SQLStorageBackend ()
{
	AuthGetter_.finish ();
	AuthInserter_.finish ();
	AuthUpdater_.finish ();
}

void SQLStorageBackend::Prepare ()
{
	QSqlQuery pragma (DB_);
	if (!pragma.exec ("PRAGMA journal_mode = TRUNCATE;"))
		LeechCraft::Util::DBLock::DumpError (pragma);
	if (!pragma.exec ("PRAGMA synchronous = OFF;"))
		LeechCraft::Util::DBLock::DumpError (pragma);
	if (!pragma.exec ("PRAGMA temp_store = MEMORY;"))
		LeechCraft::Util::DBLock::DumpError (pragma);

	AuthGetter_ = QSqlQuery (DB_);
	AuthGetter_.prepare ("SELECT "
			"login, "
			"password "
			"FROM sitesAuth "
			"WHERE realm = :realm");

	AuthInserter_ = QSqlQuery (DB_);
	AuthInserter_.prepare ("INSERT INTO sitesAuth ("
			"realm, "
			"login, "
			"password"
			") VALUES ("
			":realm, "
			":login, "
			":password"
			")");

	AuthUpdater_ = QSqlQuery (DB_);
	AuthUpdater_.prepare ("UPDATE sitesAuth SET "
			"login = :login, "
			"password = :password "
			"WHERE realm = :realm");
}

void SQLStorageBackend::GetAuth (const QString& realm,
		QString& login, QString& password) const
{
	AuthGetter_.bindValue (":realm", realm);

	if (!AuthGetter_.exec ())
	{
		LeechCraft::Util::DBLock::DumpError (AuthGetter_);
		return;
	}
	if (!AuthGetter_.next ())
	{
		AuthGetter_.finish ();
		return;
	}

	login = AuthGetter_.value (0).toString ();
	password = AuthGetter_.value (1).toString ();
	AuthGetter_.finish ();
}

void SQLStorageBackend::SetAuth (const QString& realm,
		const QString& login, const QString& password)
{
	AuthGetter_.bindValue (":realm", realm);

	if (!AuthGetter_.exec ())
	{
		LeechCraft::Util::DBLock::DumpError (AuthGetter_);
		return;
	}

	AuthGetter_.finish ();

	if (AuthGetter_.size () <= 0)
	{
		AuthInserter_.bindValue (":realm", realm);
		AuthInserter_.bindValue (":login", login);
		AuthInserter_.bindValue (":password", password);
		if (!AuthInserter_.exec ())
		{
			LeechCraft::Util::DBLock::DumpError (AuthInserter_);
			return;
		}
		AuthInserter_.finish ();
	}
	else
	{
		AuthUpdater_.bindValue (":realm", realm);
		AuthUpdater_.bindValue (":login", login);
		AuthUpdater_.bindValue (":password", password);
		if (!AuthUpdater_.exec ())
		{
			LeechCraft::Util::DBLock::DumpError (AuthUpdater_);
			return;
		}
		AuthUpdater_.finish ();
	}
}

void SQLStorageBackend::InitializeTables ()
{
	QSqlQuery query (DB_);

	if (!query.exec ("CREATE TABLE sitesAuth ("
				"realm TEXT PRIMARY KEY, "
				"login TEXT, "
				"password TEXT"
				");"))
	{
		LeechCraft::Util::DBLock::DumpError (query);
		return;
	}

	if (!query.exec ("CREATE UNIQUE INDEX sitesAuth_realm "
				"ON sitesAuth (realm);"))
		LeechCraft::Util::DBLock::DumpError (query);
}


