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

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

#include <QString>
#include <QDoubleSpinBox>
#include <QDebug>

QString Unit::formatDuration(quint64 msecs, bool include_hundredths)
{
	quint64 days = msecs / 1000 / 60 / 60 / 24;
	msecs -= days * 1000 * 60 * 60 * 24;

	quint64 hours = msecs / 1000 / 60 / 60;
	msecs -= hours * 1000 * 60 * 60;

	quint64 minutes = msecs / 1000 / 60;
	msecs -= minutes * 1000 * 60;

	quint64 seconds = msecs / 1000;
	msecs -= seconds * 1000;

	QString result;

	if (days)
		result += QString("%1:").arg(days);

	if (hours || days)
		result += QString("%1:").arg(hours);

	result += QString("%1:%2")
			.arg(minutes, (hours || days) ? 2 : 0, 10, QChar('0'))
			.arg(seconds, 2, 10, QChar('0'));

	if (include_hundredths)
		result += QString("%1%2")
				.arg(Veneer::decimalSymbol())
				.arg(static_cast<quint64>(msecs / 10), 2, 10, QChar('0'));

	return result;
}

QString Unit::formatDistance(quint64 mm, double& value, QString& unit)
{
	value = mm / 1000.0 / 1000.0; // to km first.
	unit = "km";

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
	{
		value *= 0.621371192; // to miles if imperial
		unit = "mi";
	}

	return QString("%1 %2").arg(Veneer::formatNumber(value)).arg(unit);
}

QString Unit::formatDistance(quint64 mm)
{
	double value;
	QString unit;
	return formatDistance(mm, value, unit);
}

void Unit::setSpinBoxDistance(QDoubleSpinBox& spinBox, quint64 mm)
{
	double value;
	QString unit;
	formatDistance(mm, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString(" %1").arg(unit));
}

QString Unit::formatPace(quint64 pace_in_msec_per_km, double& value, QString& unit)
{
	value = pace_in_msec_per_km;
	unit = "km";

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
	{
		value /= 0.621371192; // to miles if imperial
		unit = "mi";
	}

	return QString("%1 /%2").arg(formatDuration(value, false)).arg(unit);
}

QString Unit::formatPace(quint64 pace_in_msec_per_km)
{
	double value;
	QString unit;
	return formatPace(pace_in_msec_per_km, value, unit);
}

QString Unit::formatSpeed(quint64 speed, double& value, QString& unit)
{
	value = speed / 1000.0;
	unit = QObject::tr("km/h");

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
	{
		value *= 0.621371192; // to miles if imperial
		unit = QObject::tr("mph");
	}

	return QString("%1 %2").arg(Veneer::formatNumber(value)).arg(unit);
}

QString Unit::formatSpeed(quint64 speed)
{
	double value = 0;
	QString unit;

	return formatSpeed(speed, value, unit);
}

void Unit::setSpinBoxSpeed(QDoubleSpinBox& spinBox, quint64 speed)
{
	double value;
	QString unit;
	formatSpeed(speed, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString(" %1").arg(unit));
}

QString Unit::formatHeight(quint64 mm, double& value, QString& unit)
{
	value = mm / 1000.0; // to meters first
	unit = 'm';

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
	{
		value = toImperialHeight(value); // to feet if imperial
		unit = "ft";
	}

	return QString("%1 %2").arg(Veneer::formatNumber(value)).arg(unit);
}

QString Unit::formatHeight(quint64 mm)
{
	double value = 0;
	QString unit;
	return formatHeight(mm, value, unit);
}

void Unit::setSpinBoxHeight(QDoubleSpinBox& spinBox, quint64 mm)
{
	double value;
	QString unit;
	formatHeight(mm, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString(" %1").arg(unit));
}

QString Unit::formatEnergy(quint32 kj, quint32& value, QString& unit)
{
	value = kj;
	unit = energyUnit();

	if (Veneer::Settings::self()->energyUnit() == kcal)
		value /= 4.1858;

	return QString("%1 %2").arg(Veneer::formatNumber(value, 0)).arg(unit);
}

QString Unit::formatEnergy(quint32 kj)
{
	quint32 value = 0;
	QString unit;

	return formatEnergy(kj, value, unit);
}

void Unit::setSpinBoxEnergy(QSpinBox& spinBox, quint32 kj)
{
	quint32 value;
	QString unit;
	formatEnergy(kj, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString(" %1").arg(unit));
}

QString Unit::energyUnit()
{
	if (Veneer::Settings::self()->energyUnit() == kcal)
		return QObject::tr("kCal");

	return QObject::tr("kJ");
}

QString Unit::formatWeight(quint64 gram, double& value, QString& unit)
{
	value = gram / 1000.0; // to kg if metric
	unit = weightUnit();

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
		value = toImperialWeight(value); // to pounds if imperial

	return QString("%1 %2").arg(Veneer::formatNumber(value, 1)).arg(unit);
}

QString Unit::formatWeight(quint64 gram)
{
	double value = 0;
	QString unit;
	return formatWeight(gram, value, unit);
}

void Unit::setSpinBoxWeight(QDoubleSpinBox& spinBox, quint64 gram)
{
	double value;
	QString unit;
	formatWeight(gram, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString(" %1").arg(unit));
}

QString Unit::weightUnit()
{
	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
		return "lb";

	return "kg";
}

QString Unit::formatTemperature(quint64 deg, double& value, QString& unit)
{
	value = deg / 10.0;
	unit = temperatureUnit();

	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
		value = toFahrenheit(value);

	return QString::fromUtf8("%1%2 %3").arg(Veneer::formatNumber(value, 1)).arg(QChar(176)).arg(unit);
}

QString Unit::formatTemperature(quint64 deg)
{
	double value = 0;
	QString unit;
	return formatTemperature(deg, value, unit);
}

void Unit::setSpinBoxTemperature(QDoubleSpinBox& spinBox, quint64 deg)
{
	double value;
	QString unit;
	formatTemperature(deg, value, unit);

	spinBox.setValue(value),
	spinBox.setSuffix(QString("%1 %2").arg(QChar(176)).arg(unit));
}

QString Unit::temperatureUnit()
{
	if (Veneer::Settings::self()->measureSystem() == Veneer::Settings::EnumMeasureSystem::Imperial)
		return "F";

	return "C";
}
