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

#include "core/activity.h"
#include "core/profile.h"
#include "core/category.h"
#include "core/equipment.h"

#include "veneer/datetime.h"
#include "veneer/locale.h"

#include "util/unit.h"

#include <QVariant>
#include <QList>
#include <QDebug>

ImportModel::ImportModel(QObject* parent, Profile& p, Activities& acts) :
	QAbstractItemModel(parent),
	m_Profile(p),
	m_Activities(acts),
	m_ImportActivities()
{
	// build a list with activities we already added to the import tree so we don't add
	// an activity twice if the same activity is in different files, for instance
	Activities alreadyAddedActivities;

	foreach(const Activity* a, m_Activities)
		if (!m_Profile.hasActivity(*a) && !Activity::hasActivity(alreadyAddedActivities, *a))
		{
			m_ImportActivities.insert(a);
			alreadyAddedActivities.append(const_cast<Activity*>(a)); // no worries, we never read the list really
		}
}

QModelIndex ImportModel::index(int row, int column, const QModelIndex&) const
{
	return createIndex(row, column);
}

void ImportModel::emitAllChanged()
{
	QModelIndex first = createIndex(0, 0);
	QModelIndex last = createIndex(rowCount() - 1, 0);
	emit dataChanged(first, last);
}

void ImportModel::selectAllImports()
{
	m_ImportActivities.clear();

	foreach(const Activity* a, m_Activities)
		m_ImportActivities.insert(a);

	emitAllChanged();
}

void ImportModel::unselectAllImports()
{
	m_ImportActivities.clear();
	emitAllChanged();
}

void ImportModel::setAllCategories(Category* c)
{
	foreach (Activity* activity, m_Activities)
		activity->setCategory(c);

	emitAllChanged();
}

void ImportModel::setAllEquipments(Equipment* e)
{
	foreach (Activity* activity, m_Activities)
		activity->setEquipment(e);

	emitAllChanged();
}

QVariant ImportModel::data(const QModelIndex& index, int role) const
{
	Activities::const_iterator i = m_Activities.constBegin();
	i += index.row();

	switch (role)
	{
		case Qt::CheckStateRole:
			if (index.column() == importCol)
				return m_ImportActivities.contains(*i) ? Qt::Checked : Qt::Unchecked;
			break;

		case sortingRole:
			switch (index.column())
			{
				case dateCol:
					return (*i)->timeStamp();

				case distanceCol:
					return (*i)->totalDistance();

				case durationCol:
					return (*i)->totalDuration();
			}
			// fall through

		case Qt::DisplayRole:
			switch (index.column())
			{
				case dateCol:
					return Veneer::formatDateTime((*i)->timeStamp().toLocalTime());

				case nameCol:
					return (*i)->name();

				case distanceCol:
					return Unit::formatDistance((*i)->totalDistance());

				case durationCol:
					return Unit::formatDuration((*i)->totalDuration());

				case categoryCol:
				{
					const Category* c = (*i)->category();
					return c != NULL ? c->name() : QVariant();
				}

				case equipmentCol:
					return (*i)->equipment() != NULL ? (*i)->equipment()->name() : "---";

				default:
					break;
			}
			break;

		case Qt::EditRole:
			switch (index.column())
			{
				case categoryCol:
					return QVariant::fromValue<Category*>((*i)->category());

				case equipmentCol:
					return QVariant::fromValue<Equipment*>((*i)->equipment());
			}
			break;

		default:
			break;
	}

	return QVariant();
}

bool ImportModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
	Activities::iterator i = m_Activities.begin();
	i += index.row();

	if (index.isValid() && (role == Qt::EditRole || role == Qt::CheckStateRole))
	{
		switch(index.column())
		{
			case importCol:
				if (m_ImportActivities.contains(*i))
					m_ImportActivities.remove(*i);
				else
					m_ImportActivities.insert(*i);
				break;

			case categoryCol:
				(*i)->setCategory(value.value<Category*>());
				break;

			case equipmentCol:
				(*i)->setEquipment(value.value<Equipment*>());
				break;

			default:
				return false;
		}

		emit dataChanged(index, index);
		return true;
	}

	return false;
}

Qt::ItemFlags ImportModel::flags(const QModelIndex& index) const
{
	if (!index.isValid())
		return Qt::ItemIsEnabled;

	Qt::ItemFlags rval = 0;

	if (index.column() == importCol)
		rval = Qt::ItemIsUserCheckable;
	else if (index.column() == categoryCol || index.column() == equipmentCol)
		rval = Qt::ItemIsEditable;

	return QAbstractItemModel::flags(index) | rval;
}

QVariant ImportModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	QStringList headers;
	headers <<
		tr("Import", "import dialog column header") <<
		tr("Date", "import dialog column header") <<
		tr("Name", "import dialog column header") <<
		tr("Distance", "import dialog column header") <<
		tr("Duration", "import dialog column header") <<
		tr("Category", "import dialog column header") <<
		tr("Equipment", "import dialog column header");

	if (role == Qt::DisplayRole && orientation == Qt::Horizontal && section >= 0 && section < headers.size())
		return headers[section];

    return QAbstractItemModel::headerData(section, orientation, role);
}

