/***************************************************************************
 *   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/category.h"
#include "core/profile.h"

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

Category::Category(Profile* profile, Category* parent, const QString& name) :
	DbItem("category", QStringList() << "id" << "profile" << "parent" << "name"),
	m_Profile(profile),
	m_Parent(parent),
	m_Name(name),
	m_SubCategories()
{
}

Category::Category(Profile* profile, Category* parent, const QSqlQuery& query) :
	DbItem(query.value(0).toULongLong(), "category", QStringList() << "id" << "profile" << "parent" << "name"),
	m_Profile(profile),
	m_Parent(parent),
	m_Name(query.value(3).toString()),
	m_SubCategories()
{
}

Category::~Category()
{
	qDeleteAll(m_SubCategories);
	m_SubCategories.clear();
}

bool Category::list(Profile* profile, Category* parent, Categories& result)
{
	QSqlQuery query;

	if (!query.prepare("SELECT " + Category().columnNames().join(",") + " FROM " + Category().tableName() + " WHERE profile=? AND parent=?"))
	{
		qWarning() << "prepare failed : " << query.lastError().text();
		return false;
	}

	query.addBindValue(profile->id());
	query.addBindValue(parent ? parent->id() : 0);

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

	while (query.next())
		result.append(new Category(profile, parent, query));

	foreach(Category* cat, result)
		if (!list(profile, cat, cat->subCategories()))
			return false;

	return true;
}

bool Category::serialize()
{
	Q_ASSERT(m_Profile);

	if (m_Profile == NULL)
	{
		qWarning() << "attempt to serialize a category without profile";
		return false;
	}

	if (isRemoved())
	{
		for (int i = 0; i < subCategories().size(); i++)
			if (subCategories()[i]->remove() == false)
				return false;

		return remove();
	}

	if (!DbItem::serialize(QVariantList() << id() << m_Profile->id() << (m_Parent ? m_Parent->id() : 0) << m_Name))
		return false;


	for (Categories::iterator i = m_SubCategories.begin(); i != m_SubCategories.end(); /* NOP */)
	{
		if (!(*i)->serialize())
			return false;

		if ((*i)->isRemoved())
		{
			delete *i;
			i = m_SubCategories.erase(i);
		}
		else
			++i;
	}

	return true;
}

Category* Category::findCategory(quint64 id, Categories& cats)
{
	if (id == 0)
		return NULL;

	foreach(Category* c, cats)
	{
		if (c->id() == id)
			return c;

		if (Category* sub = findCategory(id, c->subCategories()))
			return sub;
	}

	return NULL;
}

bool Category::indirectlyContains(const Category* parent, const Category* child)
{
	if (parent == child)
		return true;

	foreach (const Category* sub, parent->subCategories())
		if (sub == child || indirectlyContains(sub, child))
			return true;

	return false;
}

void Category::toComboBox(QComboBox* combo, Categories& list, quint32 level)
{
	foreach (Category* c, list)
	{
		if (c->isRemoved())
			continue;

		QString s = QString().fill(' ', level * 4);

		combo->addItem(s + c->name(), QVariant::fromValue<Category*>(c));
		toComboBox(combo, c->subCategories(), level + 1);
	}
}
