/***************************************************************************
 *	Copyright (C) 2010 by cazou88											*
 *	cazou88@users.sourceforge.net											*
 *																			*
 *	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.,											*
 *	59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.				*
 ***************************************************************************/

#include <algorithm>           // for sort
#include <klocalizedstring.h>  // for i18n
#include <qdebug.h>            // for QDebug
#include <qglobal.h>           // for qSwap, Q_UNUSED, qDebug
#include <qicon.h>             // for QIcon
#include <qstringliteral.h>    // for QStaticStringData, QStringLiteral

#include "common.h"            // for PACKAGE_AVAILABLE, QueueSingleton
#include "packagelistitem.h"   // for PackageListItem
#include "packagelistmodel.h"
#include "queue.h"             // for Queue

class QObject;

PackageListModel::PackageListModel(QObject *parent)
 : QAbstractItemModel(parent)
{
}

PackageListModel::~PackageListModel()
{
	while (!m_packages.isEmpty())
		delete m_packages.takeLast();
}

auto PackageListModel::packages() const -> QList<PackageListItem*>
{
	return m_packages;
}

void PackageListModel::setPackages(QList<PackageListItem*>& packages)
{
	// Remove all rows
	beginRemoveRows(QModelIndex(), 0, rowCount());
	while (!m_packages.isEmpty())
		delete m_packages.takeLast();
	endRemoveRows();
	if (packages.count() <= 0)
	{
		m_packages.clear();
		return;
	}
	beginInsertRows(QModelIndex(), 0, packages.count() - 1);
	m_packages = packages;
	endInsertRows();
}

// Implementation of pure virtual methods to be implemented.
auto PackageListModel::columnCount(const QModelIndex& parent) const -> int
{
	if (parent.isValid())
		return 0;
	return 5;
}

auto PackageListModel::data(const QModelIndex& index, int role) const -> QVariant
{
	if (!index.isValid())
		return QVariant();

	auto *p = static_cast<PackageListItem*>(index.internalPointer());
	if (!p)
		return QVariant();

	switch(index.column())
	{
	case 0:
		if (role == Qt::DisplayRole)
			return QVariant(p->name());
		if (role == Qt::DecorationRole && p->status() & PACKAGE_AVAILABLE)
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_package")));
		if (role == Qt::DecorationRole)
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_stable")));
		break;
	case 1:
		if (role == Qt::DecorationRole && p->isInWorld())
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_world")));
		break;
	case 2:
		if (role == Qt::DecorationRole && QueueSingleton::Instance()->isQueued(p->id()))
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_queue")));
		break;
	case 3:
		if (role == Qt::DisplayRole)
			return QVariant(p->update());
		break;
	case 4:
		if (role == Qt::DisplayRole)
			return QVariant(p->description());
		break;
	default:
		qDebug() << "Error: invalid column!";
		break;
	}

	return QVariant();
}

auto PackageListModel::index(int row, int column, const QModelIndex& parent) const -> QModelIndex
{
	Q_UNUSED(parent)
	if (row >= 0 && row < m_packages.count())
		return createIndex(row, column, m_packages[row]);
			return QModelIndex();
}

auto PackageListModel::hasChildren(const QModelIndex& parent) const -> bool
{
	//parent.isValid is true for actual items, which don't have children (we're flat), but false for the root
	//which needs to return true here
	return !parent.isValid();
}

auto PackageListModel::parent(const QModelIndex& index) const -> QModelIndex
{
	Q_UNUSED(index)
	return QModelIndex();
}

auto PackageListModel::rowCount(const QModelIndex& parent) const -> int
{
	if (parent.isValid())
		return 0;

	return m_packages.count();
}

auto PackageListModel::headerData(int section, Qt::Orientation orientation, int role) const -> QVariant
{
	if (orientation != Qt::Horizontal)
		return QVariant();

	switch (section)
	{
	case 0:
		if (role == Qt::DisplayRole)
			return QVariant(i18n("Packages (%1)", rowCount()));
		break;
	case 1:
		if (role == Qt::DecorationRole)
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_world_column")));
		break;
	case 2:
		if (role == Qt::DecorationRole)
			return QVariant(QIcon::fromTheme(QStringLiteral("kuroo_queued_column")));
		break;
	case 3:
		if (role == Qt::DisplayRole)
			return QVariant(QStringLiteral("Update"));
		break;
	case 4:
		if (role == Qt::DisplayRole)
			return QVariant(QStringLiteral("Description"));
		break;
	default:
		qDebug() << "Error: invalid column!";
		break;
	}

	return QVariant();
}

auto PackageListModel::packageLessThan(PackageListItem *p1, PackageListItem *p2) -> bool
{
	return p1->name() < p2->name();
}

auto PackageListModel::packageMoreThan(PackageListItem *p1, PackageListItem *p2) -> bool
{
	return p1->name() > p2->name();
}

void PackageListModel::sort(int column, Qt::SortOrder order)
{
	if (column != 0)
		return;

	if (order == Qt::AscendingOrder)
		std::sort(m_packages.begin(), m_packages.end(), packageLessThan);
	else
		std::sort(m_packages.begin(), m_packages.end(), packageMoreThan);
}
