/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "batteryhistorydialog.h"
#include <algorithm>
#include <qwt_global.h>
#include <qwt_plot_curve.h>
#include <qwt_curve_fitter.h>
#include <qwt_legend.h>
#include <qwt_dyngrid_layout.h>

#if QWT_VERSION >= 0x060100
#include <qwt_plot_legenditem.h>
#endif

#include <util/util.h>
#include "batteryinfo.h"

namespace LeechCraft
{
namespace Liznoo
{
	BatteryHistoryDialog::BatteryHistoryDialog (int histSize, QWidget *parent)
	: QDialog (parent)
	, Percent_ (new QwtPlotCurve (tr ("Percentage")))
	, Energy_ (new QwtPlotCurve (tr ("Energy rate")))
	, Temperature_ (new QwtPlotCurve (tr ("Temperature")))
	{
		Ui_.setupUi (this);

		Ui_.PercentPlot_->setAxisAutoScale (QwtPlot::xBottom, false);
		Ui_.PercentPlot_->setAxisAutoScale (QwtPlot::yLeft, false);
		Ui_.PercentPlot_->setAxisScale (QwtPlot::xBottom, 0, histSize);
		Ui_.PercentPlot_->setAxisScale (QwtPlot::yLeft, 0, 100);
		Ui_.PercentPlot_->enableAxis (QwtPlot::yRight);
		Ui_.PercentPlot_->setAxisTitle (QwtPlot::yLeft, tr ("Percent"));
		Ui_.PercentPlot_->setAxisTitle (QwtPlot::yRight, tr ("Energy rate, W"));

		QColor percentColor (Qt::blue);
		Percent_->setPen (QPen (percentColor));
		percentColor.setAlpha (20);
		Percent_->setBrush (percentColor);

		Percent_->setRenderHint (QwtPlotItem::RenderAntialiased);
		Percent_->attach (Ui_.PercentPlot_);

		QColor energyColor (Qt::red);
		Energy_->setPen (QPen (energyColor));
		energyColor.setAlpha (20);
		Energy_->setBrush (energyColor);

		Energy_->setRenderHint (QwtPlotItem::RenderAntialiased);
		Energy_->setYAxis (QwtPlot::yRight);
		Energy_->attach (Ui_.PercentPlot_);

		QColor tempColor (Qt::green);
		Temperature_->setPen (QPen (tempColor));
		tempColor.setAlpha (20);
		Temperature_->setBrush (tempColor);

		Temperature_->setRenderHint (QwtPlotItem::RenderAntialiased);

#if QWT_VERSION >= 0x060100
		auto item = new QwtPlotLegendItem;
		item->setMaxColumns (1);
		item->setAlignment (Qt::AlignTop | Qt::AlignLeft);
		item->attach (Ui_.PercentPlot_);

		auto bgColor = palette ().color (QPalette::Button);
		bgColor.setAlphaF (0.8);
		item->setBackgroundBrush (bgColor);
		item->setBorderRadius (3);
		item->setBorderPen (QPen (palette ().color (QPalette::Dark), 1));
#else
		QwtLegend *legend = new QwtLegend;
		legend->setItemMode (QwtLegend::ClickableItem);
		Ui_.PercentPlot_->insertLegend (legend, QwtPlot::ExternalLegend);

		auto layout = qobject_cast<QwtDynGridLayout*> (legend->contentsWidget ()->layout ());
		if (layout)
			layout->setMaxCols (1);
		else
			qWarning () << Q_FUNC_INFO
					<< "legend contents layout is not a QwtDynGridLayout:"
					<< legend->contentsWidget ()->layout ();

		Ui_.InfoFrame_->layout ()->addWidget (legend);
#endif
	}

	void BatteryHistoryDialog::UpdateHistory (const QLinkedList<BatteryHistory>& hist, const BatteryInfo& info)
	{
		QVector<double> xdata (hist.size ());
		QVector<double> percents (hist.size ());
		QVector<double> energy (hist.size ());
		QVector<double> temperature (hist.size ());

		bool setTemperature = false;
		int i = 0;
		std::for_each (hist.begin (), hist.end (),
				[&] (const BatteryHistory& bh) -> void
				{
					percents [i] = bh.Percentage_;
					energy [i] = bh.EnergyRate_;

					temperature [i] = bh.Temperature_ - 273.15;
					setTemperature = bh.Temperature_ || setTemperature;

					xdata [i] = i;
					++i;
				});
		Percent_->setSamples (xdata, percents);
		Energy_->setSamples (xdata, energy);
		if (setTemperature)
		{
			Temperature_->attach (Ui_.PercentPlot_);
			Temperature_->setSamples (xdata, temperature);
		}

		Ui_.PercentPlot_->replot ();

		QString chargeStateStr;
		if (info.TimeToEmpty_ && info.TimeToEmpty_ < 3600 * 24)
		{
			Ui_.RemainingTimeLabel_->setVisible (true);
			Ui_.RemainingTime_->setVisible (true);
			Ui_.RemainingTime_->setText (Util::MakeTimeFromLong (info.TimeToEmpty_));

			chargeStateStr = tr ("(discharging)");
		}
		else if (info.TimeToFull_ && info.TimeToFull_ < 3600 * 24)
		{
			Ui_.RemainingTimeLabel_->setVisible (true);
			Ui_.RemainingTime_->setVisible (true);
			Ui_.RemainingTime_->setText (Util::MakeTimeFromLong (info.TimeToFull_));

			chargeStateStr = tr ("(charging)");
		}
		else
		{
			Ui_.RemainingTimeLabel_->setVisible (false);
			Ui_.RemainingTime_->setVisible (false);
		}

		if (info.Temperature_ > 100)
		{
			Ui_.TempLabel_->setVisible (true);
			Ui_.Temp_->setVisible (true);
			Ui_.Temp_->setText (QString::fromUtf8 ("%1 °C").arg (info.Temperature_ - 273.15));
		}
		else
		{
			Ui_.TempLabel_->setVisible (false);
			Ui_.Temp_->setVisible (false);
		}

		if (info.Voltage_)
		{
			Ui_.VoltageLabel_->setVisible (true);
			Ui_.Voltage_->setVisible (true);
			Ui_.Voltage_->setText (tr ("%1 V").arg (info.Voltage_, 0, 'f', 3));
		}
		else
		{
			Ui_.VoltageLabel_->setVisible (false);
			Ui_.Voltage_->setVisible (false);
		}

		const bool energyAvailable = info.DesignEnergyFull_ > 1 && info.Energy_ > 1 && info.EnergyFull_ > 1;
		if (energyAvailable)
		{
			Ui_.DesignCapacity_->setText (tr ("%1 mAh").arg (info.DesignEnergyFull_, 0, 'f', 2));
			Ui_.LastFullCapacity_->setText (tr ("%1 mAh").arg (info.EnergyFull_, 0, 'f', 2));
			Ui_.Capacity_->setText (tr ("%1 mAh").arg (info.Energy_, 0, 'f', 2));

			const auto ratio = info.EnergyFull_ / info.DesignEnergyFull_;
			QString ratioText;
			if (ratio > 0.9)
				ratioText = tr ("awesome");
			else if (ratio > 0.7)
				ratioText = tr ("good");
			else if (ratio > 0.4)
				ratioText = tr ("degraded");
			else
				ratioText = tr ("bad");
			Ui_.Health_->setText (tr ("%1% (%2)")
					.arg (ratio * 100, 0, 'f', 1)
					.arg (ratioText));
		}
		Ui_.DesignCapacityLabel_->setVisible (energyAvailable);
		Ui_.DesignCapacity_->setVisible (energyAvailable);
		Ui_.LastFullCapacityLabel_->setVisible (energyAvailable);
		Ui_.LastFullCapacity_->setVisible (energyAvailable);
		Ui_.CapacityLabel_->setVisible (energyAvailable);
		Ui_.Capacity_->setVisible (energyAvailable);
		Ui_.HealthLabel_->setVisible (energyAvailable);
		Ui_.Health_->setVisible (energyAvailable);

		Ui_.PercentageLabel_->setText (QString::number (info.Percentage_) + "% " + chargeStateStr);
	}
}
}
