/* 
 * This file is part of DesktopBSD, see the README file.
 *
 * Author: Peter Hofer <ph@desktopbsd.net>
 *         (C) 2004, 2005
 *
 * Copyright: BSD, see the COPYING file included in this distribution
 *
 */

#include <qapplication.h>
#include <qtimer.h>
#include <qpixmap.h>
#include <kpassivepopup.h>
#include <qtooltip.h>
#include <qpopupmenu.h>

#include <dbsdglobal.h>
#include <battery.h>
#include <batterytray.h>

#include "batterysettings.h"
#include "frmconfig.h"

/* Minimum/maximum value for update interval (in seconds) */
#define _UPDATE_MIN 5
#define _UPDATE_MAX 30

BatteryTray::BatteryTray() {
	DBSDIconLoader  *iloader = DBSDGlobal::getIconLoader();
	
	menu = new QPopupMenu();
	menu->insertItem(iloader->loadIcon("configure", DBSDIconLoader::Size16x16),
	                          tr("Configure..."), this, SLOT(openConfigDialog()));
	menu->insertItem(iloader->loadIcon("exit", DBSDIconLoader::Size16x16),
	                          tr("Quit"), qApp, SLOT(quit()));
	setPopup(menu);
	
	imgBattery = iloader->loadIcon("dbsd-battinfo-battery", DBSDIconLoader::Size22x22)
							.convertToImage();

	imgRecharge = iloader->loadIcon("dbsd-battinfo-recharge", DBSDIconLoader::Size22x22)
							.convertToImage();
	
	pixPower = iloader->loadIcon("dbsd-battinfo-power", DBSDIconLoader::Size22x22);
	
	previousRechargeLife = -1;
	previousPowerSource = -1;
	timer = NULL;
}

BatteryTray::~BatteryTray()
{
	if (menu != NULL)
	{
		delete menu;
	}

	if (timer != NULL)
	{
		delete timer;
	}
}

void	BatteryTray::start() {
	uint	updateTime = Battery::infoExpires();

	/* Check for bad values and replace
	 * them if necessary.
	 */
	if(updateTime < _UPDATE_MIN)
		updateTime = _UPDATE_MIN;
	else if(updateTime > _UPDATE_MAX)
		updateTime = _UPDATE_MAX;

	updateStatus();

	timer = new QTimer(this);
	connect(timer,  SIGNAL(timeout()),  SLOT(updateStatus()));
	timer->start(updateTime * 1000,  false);
}


void  BatteryTray::updateStatus() {
	QImage  image;
	
	static bool lifeCriticalShown = false,
					lifeLowShown = false;

	int  powersrc = Battery::powerSource();
	int  time = Battery::getTime();
	int  life = Battery::getLife();

	QString  tipText = tr("Power Source: %1\n", "The power source of a mobile device");

	if(powersrc == Battery::PS_ACLine) {
		tipText = tipText.arg(tr("AC Line"));

		if(life >= 0  &&  life  <= 100)
			image = imgRecharge;
		else
			setIcon(pixPower);

		lifeCriticalShown = false;
		lifeLowShown = false;
	} else {
		tipText = tipText.arg(tr("Battery"));
		image = imgBattery;

		BatterySettings bs;
		if (life <= bs.getCriticalWarningAt())
		{
			if (bs.isCriticalWarningEnabled() && !lifeCriticalShown)
			{
				KPassivePopup::message(tr("Critical Battery"), tr("Battery status: %1%.").arg(life), image, winId());
				lifeCriticalShown = true;
			}
		}
		else
		{
			lifeCriticalShown = false;
		}

		if (life <= bs.getLowWarningAt())
		{
			if (bs.isLowWarningEnabled() && !lifeLowShown && !lifeCriticalShown)
			{
				KPassivePopup::message(tr("Low Battery"), tr("Battery status: %1%.").arg(life), image, winId());
				lifeLowShown = true;
			}
		}
		else
		{
			lifeLowShown = false;
		}
	}

	if(life >= 0 && life <= 100) {
		int rlife = (float) (image.height() - 9) / 100 * (101 - life) + 4;
		
		if(rlife != previousRechargeLife || powersrc != previousPowerSource)
		{
			image.detach();

			for(uint y = 0;  y < rlife;  ++y)
			{
				for(uint x = 0;  x < image.width();  ++x)
				{
					uint rgba = image.pixel(x, y);
	
					/* Don't change transparent pixels */
					if(qAlpha(rgba) < 190)
						continue;
				
					QColor c;
					int h, s ,v;
					c.setRgb(rgba);
					c.getHsv(&h, &s, &v);
					c.setHsv(h, 0, ((v *= 1.1) > 255) ? 255 : v);
					image.setPixel(x, y, c.rgb());
				}
			}

			previousPowerSource = powersrc;
			previousRechargeLife = rlife;
			pixPreviousRecharge = image;
			setIcon(pixPreviousRecharge);
		}

		tipText += tr("Battery Status: %1 %\n").arg(life);
	}

	if(time > 0) {
		tipText += tr("Time left: ~ %1");

		int  minutes = time % 60,
		               hours = time / 60;

		if(hours == 0)
			tipText = tipText.arg(tr("%1 minutes")).arg(minutes);
		else {
			if(minutes >= 10)
				tipText = tipText.arg(tr("%1:%2 hours"));
			else
				tipText = tipText.arg(tr("%1:0%2 hours"));

			tipText = tipText.arg(hours).arg(minutes);
		}
	}

	setToolTip(tipText);
}

void BatteryTray::mouseDoubleClickEvent(QMouseEvent *e) {
	if(e != NULL)
		openConfigDialog();
}

void BatteryTray::openConfigDialog() {
	FrmConfig fc;
	fc.exec();
}
