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

#include "core/activity.h"

#include "veneer/datetime.h"

#include "util/unit.h"

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

QModelIndex ActivityModel::first()
{
	if (rowCount() > 0)
		return createIndex(0, 0);

	return QModelIndex();
}

QModelIndex ActivityModel::find(const Activity* activity)
{
	quint32 count = 0;
	foreach(const Activity* a, m_Activities)
	{
		if (a == activity)
			return createIndex(count, 0);
		count++;
	}

	return QModelIndex();
}

void ActivityModel::add(Activity* a)
{
	beginInsertRows(QModelIndex(), rowCount(), rowCount());
	m_Activities.append(a);
	endInsertRows();
}

void ActivityModel::remove(Activity* a)
{
	QModelIndex idx = find(a);

	if (!idx.isValid())
		return;

	beginRemoveRows(QModelIndex(), idx.row(), idx.row());

	ModelActivities::iterator i = m_Activities.begin();

	while (i != m_Activities.end())
		if (*i == a)
			i = m_Activities.erase(i);
		else
			i++;

	endRemoveRows();
}

void ActivityModel::clear()
{
	if (rowCount() > 0)
	{
		beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
		m_Activities.clear();
		endRemoveRows();
	}
}

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

Activity* ActivityModel::activity(const QModelIndex& index)
{
	if (index.row() >= m_Activities.size())
		return NULL;

	ModelActivities::iterator i = m_Activities.begin();
	i += index.row();

	return *i;
}

const Activity* ActivityModel::activity(const QModelIndex& index) const
{
	if (index.row() >= m_Activities.size())
		return NULL;

	ModelActivities::const_iterator i = m_Activities.constBegin();
	i += index.row();

	return *i;
}

QVariant ActivityModel::data(const QModelIndex& index, int role) const
{
	const Activity* a = activity(index);

	if (a == NULL)
		return QVariant();

	switch (role)
	{
		case Qt::SizeHintRole:
			return QSize(0, 22);

		case sortingRole:
			switch (index.column())
			{
				case ActivityTree::dateCol:          return a->timeStamp();
				case ActivityTree::distanceCol:      return a->totalDistance();
				case ActivityTree::durationCol:      return a->totalDuration();
				case ActivityTree::avgPaceCol:       return a->averagePace();
				case ActivityTree::avgSpeedCol:      return a->averageSpeed();
				case ActivityTree::maxSpeedCol:      return a->maxSpeed();
				case ActivityTree::energyConsCol:    return a->energyConsumption();
				case ActivityTree::avgHRCol:         return a->averageHeartRate();
				case ActivityTree::maxHRCol:         return a->maxHeartRate();
				case ActivityTree::avgCadenceCol:    return a->averageCadence();
				case ActivityTree::ascentCol:        return a->totalAscent();
				case ActivityTree::descentCol:       return a->totalDescent();
			}
			// fall through

		case Qt::EditRole:
		case Qt::DisplayRole:
			switch (index.column())
			{
				case ActivityTree::dateCol:          return Veneer::formatDateTime(a->timeStamp());
				case ActivityTree::nameCol:          return a->name();
				case ActivityTree::distanceCol:      return Unit::formatDistance(a->totalDistance());
				case ActivityTree::durationCol:      return Unit::formatDuration(a->totalDuration());
				case ActivityTree::avgPaceCol:       return Unit::formatPace(a->averagePace());
				case ActivityTree::avgSpeedCol:      return Unit::formatSpeed(a->averageSpeed());
				case ActivityTree::maxSpeedCol:      return Unit::formatSpeed(a->maxSpeed());
				case ActivityTree::energyConsCol:    return Unit::formatEnergy(a->energyConsumption());
				case ActivityTree::avgHRCol:         return QString("%1 bpm").arg(a->averageHeartRate());
				case ActivityTree::maxHRCol:         return QString("%1 bpm").arg(a->maxHeartRate());
				case ActivityTree::avgCadenceCol:    return QString("%1 rpm").arg(a->averageCadence());
				case ActivityTree::ascentCol:        return Unit::formatHeight(a->totalAscent());
				case ActivityTree::descentCol:       return Unit::formatHeight(a->totalDescent());
				default:                             break;
			}
			break;

		default:
			break;
	}

	return QVariant();
}

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

	if (index.isValid() && role == Qt::EditRole)
	{
		switch(index.column())
		{
			case ActivityTree::nameCol:      (*i)->setName(value.toString()); break;
			default:                         return false;
		}

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

	return false;
}

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

	Qt::ItemFlags rval = 0;

	if (index.column() == ActivityTree::nameCol)
		rval = Qt::ItemIsEditable;

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

QVariant ActivityModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	static const QStringList headers = QStringList() <<
		tr("Date", "acvitity column header") <<
		tr("Name", "acvitity column header") <<
		tr("Distance", "acvitity column header") <<
		tr("Duration", "acvitity column header") <<
		tr("Avg. Pace", "acvitity column header") <<
		tr("Avg. Speed", "acvitity column header") <<
		tr("Max. Speed", "acvitity column header") <<
		tr("Energy Con.", "acvitity column header") <<
		tr("Avg. HR", "acvitity column header") <<
		tr("Max. HR", "acvitity column header") <<
		tr("Avg. Cadence", "acvitity column header") <<
		tr("Ascent", "acvitity column header") <<
		tr("Descent", "acvitity column header");

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

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