/***************************************************************************
 *   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/dbitem.h"

#include <QDebug>
#include <QStringList>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>

// FIXME: workaround for QTBUG-7988
// need to link against libsqlite3 if enabled
// #define DEBUG_SQLITE_TRIGGERS

#if defined(DEBUG_SQLITE_TRIGGERS)
#include <QSqlDatabase>
#include <QSqlDriver>
#include <sqlite3.h>
#endif

DbItem::DbItem(const QString& table_name, const QStringList& cols) :
	m_Id(0),
	m_Dirty(false),
	m_Removed(false),
	m_New(true),
	m_TableName(table_name),
	m_ColumnNames(cols)
{
}

DbItem::DbItem(quint64 id, const QString& table_name, const QStringList& cols) :
	m_Id(id),
	m_Dirty(false),
	m_Removed(false),
	m_New(false),
	m_TableName(table_name),
	m_ColumnNames(cols)
{
	Q_ASSERT(id > 0);
}

bool DbItem::serialize(QVariantList values)
{
	Q_ASSERT(!isRemoved());

	if (isRemoved())
	{
		qDebug() << "trying to serialize a removed dbitem. table=" << tableName() << ", id=" << id();
		return false;
	}

	if (!isDirty() && !isNew())
		return true;

// 	qDebug() << "serialize item " << id() << " to table " << tableName() << ": new=" << isNew() << ", dirty=" << isDirty();

	QSqlQuery query;
	QString s;

	if (values.size() != m_ColumnNames.size())
		qWarning() << "size of values is " << values.size() << " while it should be " << m_ColumnNames.size();

	if (isNew())
	{
		Q_ASSERT(values[0].isNull());

		s = "INSERT INTO " + m_TableName + " (" + m_ColumnNames.join(", ") + ") VALUES (";
		for (int i = 0; i < m_ColumnNames.size() - 1; i++)
			s += "?, ";
		s +=  "?)";
	}
	else
		s = "UPDATE " + m_TableName + " SET " + m_ColumnNames.join("=?, ") + "=? WHERE id=?";

	if (!query.prepare(s))
	{
		qWarning() << "prepare of " << query.lastQuery() << " failed : " << query.lastError().text();
		return false;
	}

	foreach (const QVariant& v, values)
		query.addBindValue(v);

	if (!isNew())
	{
		Q_ASSERT(!id().isNull());
		query.addBindValue(id());
	}

	if (!query.exec())
	{
		qWarning() << "exec of " << query.lastQuery() << " failed : " << query.lastError().text();

		qWarning() << "id: " << id();

		QVariantList list = query.boundValues().values();
		for (int i = 0; i < list.size(); ++i)
			qDebug() << i << ": " << list.at(i).toString().toAscii().data() << endl;

#if defined(DEBUG_SQLITE_TRIGGERS)
		QVariant v = QSqlDatabase::database().driver()->handle();
		if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0)
		{
			sqlite3* handle = *static_cast<sqlite3**>(v.data());
			if (handle != NULL)
				qDebug() << "sqlite error: " << sqlite3_errmsg(handle);
		}
#endif

		return false;
	}

	if (isNew())
	{
		setNew(false);
		m_Id = query.lastInsertId();
	}

	setDirty(false);

	return true;
}

bool DbItem::remove()
{
	if (id() == 0)
		return true;

	QSqlQuery query;

	if (!query.prepare("DELETE FROM " + m_TableName + " WHERE id=?"))
	{
		qWarning() << "prepare of " << query.lastQuery() << " failed for id " << id() << ": " << query.lastError().text();
		return false;
	}

	query.addBindValue(id());

	if (!query.exec())
	{
		qWarning() << "exec of " << query.lastQuery() << " failed for id " << id() << ": " << query.lastError().text();
		return false;
	}

	return true;
}
