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

#include "core/activity.h"
#include "core/lap.h"
#include "core/track.h"
#include "core/trackpoint.h"

#include "util/unit.h"

#include <QXmlStreamWriter>
#include <QDateTime>
#include <QDebug>

GarminTrainingCenterExporter::GarminTrainingCenterExporter() :
	ExporterInterface()
{
}

bool GarminTrainingCenterExporter::canExport(const QString& suffix, const Activities&)
{
	return suffix == "tcx";
}

bool GarminTrainingCenterExporter::writeTrack(QXmlStreamWriter& xml, const Track& trk)
{
	quint64 distance = 0;

	xml.writeStartElement("Track");

	const TrackPoint* prev = NULL;

	foreach(const TrackPoint* tp, trk.trackPoints())
	{
		xml.writeStartElement("Trackpoint");

		xml.writeTextElement("Time", tp->timeStamp().toString(Qt::ISODate) + 'Z');

		if (tp->position().isValid())
		{
			xml.writeStartElement("Position");
			xml.writeTextElement("LatitudeDegrees", QString::number(tp->position().latitude(), 'f', 9));
			xml.writeTextElement("LongitudeDegrees", QString::number(tp->position().longitude(), 'f', 9));
			xml.writeEndElement();
		}

		xml.writeTextElement("AltitudeMeters", QString::number(tp->altitude() / 1000.0));

		if (tp->position().isValid() && prev && prev->position().isValid())
		{
			distance += prev->position().distanceTo(tp->position());
			xml.writeTextElement("DistanceMeters", QString::number(distance / 1000.0));
		}

		if (tp->heartRate() > 0)
		{
			xml.writeStartElement("HeartRateBpm");
			xml.writeAttribute("xsi:type", "HeartRateInBeatsPerMinute_t");
			xml.writeTextElement("Value", QString::number(tp->heartRate()));
			xml.writeEndElement();
		}

		xml.writeTextElement("Cadence", QString::number(tp->cadence()));

		xml.writeTextElement("SensorState", "Present");

		prev = tp;

		xml.writeEndElement();
	}

	xml.writeEndElement();

	return true;
}


bool GarminTrainingCenterExporter::writeLap(QXmlStreamWriter& xml, const Lap& lap)
{
	xml.writeStartElement("Lap");
	xml.writeAttribute("StartTime", lap.startTime().toString(Qt::ISODate) + 'Z');
	xml.writeTextElement("TotalTimeSeconds", QString::number(lap.duration() / 1000.0));
	xml.writeTextElement("DistanceMeters", QString::number(lap.distance() / 1000.0));
	xml.writeTextElement("MaximumSpeed", QString::number(lap.maximumSpeed() / 1000.0));
	xml.writeTextElement("Calories", QString::number(Unit::toKiloCalories(lap.energyConsumption())));

	if (lap.averageHeartRate() > 0)
	{
		xml.writeStartElement("AverageHeartRateBpm");
		xml.writeAttribute("xsi:type", "HeartRateInBeatsPerMinute_t");
		xml.writeTextElement("Value", QString::number(lap.averageHeartRate()));
		xml.writeEndElement();
	}

	if (lap.maximumHeartRate() > 0)
	{
		xml.writeStartElement("MaximumHeartRateBpm");
		xml.writeAttribute("xsi:type", "HeartRateInBeatsPerMinute_t");
		xml.writeTextElement("Value", QString::number(lap.maximumHeartRate()));
		xml.writeEndElement();
	}

	xml.writeTextElement("Intensity", "Active");
	xml.writeTextElement("Cadence", QString::number(lap.averageCadence()));
	xml.writeTextElement("TriggerMethod", "Manual");

	foreach(const Track* track, lap.tracks())
		writeTrack(xml, *track);

	xml.writeEndElement();

	return true;
}

bool GarminTrainingCenterExporter::writeActivity(QXmlStreamWriter& xml, const Activity& a)
{
	xml.writeStartElement("Activity");

	// TODO: set sport attribute based on category
	xml.writeAttribute("Sport", "Biking");

	xml.writeTextElement("Id", a.timeStamp().toString(Qt::ISODate) + 'Z');

	foreach(const Lap* lap, a.laps())
		writeLap(xml, *lap);

	xml.writeEndElement();

	return true;
}

bool GarminTrainingCenterExporter::writeRootElement(QXmlStreamWriter& xml, const Activities&)
{
	xml.writeStartElement("TrainingCenterDatabase");
	xml.writeAttribute("xmlns", "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2");
	xml.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	xml.writeAttribute("xsi:schemaLocation", "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd");

	return true;
}

bool GarminTrainingCenterExporter::writeActivities(QXmlStreamWriter& xml, const Activities& activities)
{
	xml.writeStartElement("Activities");

	foreach(const Activity* a, activities)
		writeActivity(xml, *a);

	xml.writeEndElement();

	return true;
}

QString GarminTrainingCenterExporter::fileFormat() const
{
	return QObject::tr("*.tcx|Garmin Training Center (*.tcx)");
}
