//
// C++ Implementation: batteryicon
//
// Author: Oliver Groß <z.o.gross@gmx.de>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
#include "batteryicon.h"
#include "common.h"
#include <QPainter>
#include <QMessageBox>

namespace qbat {
	QDir CBatteryIcon::sysfsDir(UI_PATH_SYSFS_DIR);
	
	CBatteryIcon::CBatteryIcon(Settings * settings, QString batteryName, QObject * parent) :
		QSystemTrayIcon(parent),
		m_Icon(28, 28),
		m_IconName(""), //alex
		m_Settings(settings)
	{
		m_Data.name = batteryName;
		
		updateIcon();
		
		connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
			this, SLOT(handleClicks(QSystemTrayIcon::ActivationReason)));
	}
	
	CBatteryIcon::~CBatteryIcon() {
	}
	
	void CBatteryIcon::updateIcon() {
	    if (m_Settings->standardIcons) //alex
	    {
	        //name is "battery[-charging][-percent]", where percent may be "caution",low,40,60,80,100 or ""
		QString m_IconName, charging, percent;

		if (m_Data.status == UI_BATTERY_CHARGING ||
		    m_Data.status == UI_BATTERY_FULL || m_Data.status==0)  charging="-charging";
		if (m_Data.relativeCharge <= 100)
		{
			     if (m_Data.relativeCharge< 0) percent="-caution";//-1 is smth. wrong?
		    else if (m_Data.relativeCharge<20) percent="-low";  //00-20
		    else if (m_Data.relativeCharge<40) percent="-040";  //20-40
		    else if (m_Data.relativeCharge<60) percent="-060";  //40-60
		    else if (m_Data.relativeCharge<80) percent="-080";  //60-80
		    else if (m_Data.relativeCharge<=100)
		      percent=QString::fromLocal8Bit(((m_Data.status==UI_BATTERY_DISCHARGING || m_Data.status==UI_BATTERY_FULL)?"-100":"")); //80-100
		}
		else
		{
		  //>100 is the same as 100?
		  if (m_Data.relativeCharge<=100)
		    percent=QString::fromLocal8Bit(((m_Data.status==UI_BATTERY_DISCHARGING || m_Data.status==UI_BATTERY_FULL)?"-100":""));
		}
		m_IconName = QString("battery")+charging+percent;
		QIcon ico = QIcon::fromTheme(m_IconName);
		if (ico.isNull()) goto draw_it;
		setIcon(ico);
		//fprintf(stderr,"set icon=%s rel=%d\n",m_IconName.toLocal8Bit().data(),m_Data.relativeCharge);
	    }
	    else
	    {
draw_it:
		m_Icon.fill(Qt::transparent);
		QPainter painter(&m_Icon);
		
		if (m_Data.currentCapacity != m_Data.fullCapacity || m_Data.status != UI_BATTERY_FULL) {
			if (m_Data.status == UI_BATTERY_DISCHARGING)
				painter.setPen(QColor(m_Settings->colors[UI_COLOR_PEN_DISCHARGE]));
			else
				painter.setPen(QColor(m_Settings->colors[UI_COLOR_PEN_CHARGE]));
			
			painter.setBrush(QColor(m_Settings->colors[UI_COLOR_BRUSH_EMPTY]));
			painter.drawRect(0, 4, 27, 23);
			
			int chargedPixels = (int)(22 * m_Data.relativeCharge / 100.0);
			
			painter.fillRect(1, 5 + 22 - chargedPixels, 26, chargedPixels, QColor(m_Settings->colors[UI_COLOR_BRUSH_CHARGED]));
			
			if (m_Data.status == UI_BATTERY_DISCHARGING)
				painter.setBrush(QColor(m_Settings->colors[UI_COLOR_BRUSH_POLE_DISCHARGE]));
			else
				painter.setBrush(QColor(m_Settings->colors[UI_COLOR_BRUSH_POLE_CHARGE]));
		}
		else {
			painter.setPen(QColor(m_Settings->colors[UI_COLOR_PEN_FULL]));
			painter.setBrush(QColor(m_Settings->colors[UI_COLOR_BRUSH_FULL]));
			painter.drawRect(0, 4, 27, 23);
			
			painter.setBrush(QColor(m_Settings->colors[UI_COLOR_BRUSH_POLE_FULL]));
		}
		painter.drawRect(7, 0, 13, 4);
		
		painter.setBrush(Qt::NoBrush);
		
		if (m_Data.relativeCharge < 100)
			((QFont&)painter.font()).setPixelSize(15);
		else
			((QFont&)painter.font()).setPixelSize(12);
		
		painter.setRenderHint(QPainter::TextAntialiasing);
		((QFont&)painter.font()).setBold(true);
		if (m_Data.relativeCharge == -1)
			painter.drawText(1, 9, 26, 16, Qt::AlignHCenter, QString('?'));
		else
			painter.drawText(1, 9, 26, 16, Qt::AlignHCenter, QString::number(m_Data.relativeCharge));
		
		setIcon(m_Icon.scaled(QSize(128,128))); //alex
	    }
	}
	
	void CBatteryIcon::updateToolTip() {
		QString newToolTip = tr("%1: %2%").arg(m_Data.name == "merged" ? tr("charge") : m_Data.name) +'\n';
		
		if (m_Data.relativeCharge == -1)
			newToolTip = newToolTip.arg('-');
		else
			newToolTip = newToolTip.arg(m_Data.relativeCharge);
		
		switch (m_Data.status) {
		case UI_BATTERY_DISCHARGING:
			newToolTip += tr("status: %1").arg(tr("discharging"));
			if (m_Data.rate>0 && m_Data.fullCapacity>100) { //alex: if fullCap not in percents
				newToolTip += '\n';
				qreal remainingTime  = (qreal)(m_Data.currentCapacity) / m_Data.rate;
				int remainingHours   = (int)remainingTime;
				int remainungMinutes = (int)(remainingTime * 60) % 60;
				newToolTip += tr("remaining time: %1:%2").arg(remainingHours, 2, 10, QChar('0')).arg(remainungMinutes, 2, 10, QChar('0'));
			}
			break;
		case UI_BATTERY_CHARGING:
			newToolTip += tr("status: %1").arg(tr("charging"));
			if (m_Data.rate>0 && m_Data.fullCapacity>100) { //alex: if fullCap not in percents
				newToolTip += '\n';
				qreal remainingTime  = (qreal)(m_Data.fullCapacity - m_Data.currentCapacity) / m_Data.rate;
				int remainingHours   = (int)remainingTime;
				int remainungMinutes = (int)(remainingTime * 60) % 60;
				newToolTip += tr("remaining time: %1:%2").arg(remainingHours, 2, 10, QChar('0')).arg(remainungMinutes, 2, 10, QChar('0'));
			}
			break;
		case UI_BATTERY_FULL:
			newToolTip += tr("status: %1").arg(tr("full"));
			break;
		default:
			newToolTip += tr("status: %1").arg(tr("unknown"));
			break;
		}

		if (m_Settings->showExtendedInfo) {
			newToolTip += '\n';

			if (m_Data.energyUnits) {
				if ((m_Data.rate>0) && (m_Data.status != UI_BATTERY_FULL)) {
					double rateW = qRound(m_Data.rate / 100000.0) / 10.0;
					if (m_Data.voltage) {
						double rateA = qRound((m_Data.rate / m_Data.voltage) / 1000.0) / 10.0;
						newToolTip += tr("current rate: %1W / %2A").arg(rateW).arg(rateA) + '\n';
					}
					else
						newToolTip += tr("current rate: %1W").arg(rateW) + '\n';
				}

				if (m_Data.fullCapacity>100) //alex: if fullCap not in percents
					newToolTip += tr("current capacity: %1mWh").arg(m_Data.currentCapacity / 1000);

				if (m_Data.fullCapacity>100)
					newToolTip += '\n' + tr("last full capacity: %1mWh").arg(m_Data.fullCapacity / 1000);

				if (m_Data.designCapacity)
					newToolTip += '\n' + tr("design capacity: %1mWh").arg(m_Data.designCapacity / 1000);
			}
			else
			{
				if ((m_Data.rate>0) && (m_Data.status != UI_BATTERY_FULL)) {
					double rateA = m_Data.rate / 100000.0;
					if (m_Data.voltage) {
						double rateW = qRound(rateA * m_Data.voltage / 100.0) / 10.0;
						if (rateW>0 && rateA>0) //alex
							newToolTip += tr("current rate: %1W / %2A").arg(rateW).arg(qRound(rateA) / 10.0) + '\n';
					}
					else {
						if (rateA>0) //alex
							newToolTip += tr("current rate: %1A").arg(qRound(rateA) / 10.0) + '\n';
					}
				}

				if (m_Data.fullCapacity>100) //alex: if fullCap not in percents
					newToolTip += tr("current capacity: %1mAh").arg(m_Data.currentCapacity / 1000);

				if (m_Data.fullCapacity>100) //alex: if fullCap not in percents
					newToolTip += '\n' + tr("last full capacity: %1mAh").arg(m_Data.fullCapacity / 1000);

				if (m_Data.designCapacity)
					newToolTip += '\n' + tr("design capacity: %1mAh").arg(m_Data.designCapacity / 1000);
			}

			if (m_Data.designCapacity && m_Data.fullCapacity < m_Data.designCapacity)
				newToolTip += '\n' + tr("capacity loss: %1%").arg((int)((1 - (double)m_Data.fullCapacity / m_Data.designCapacity) * 100));
		}

		setMessage(newToolTip);
	}
	
	void CBatteryIcon::updateData(int currentCapacity, int fullCapacity, int designCapacity, int rate, int voltage, int status, bool energyUnits) {
		m_Data.energyUnits = energyUnits;
		
		bool statusUpdated=false; //alex
		
		bool noupdate = true;
		
		if (rate != m_Data.rate) {
			noupdate = false;
			m_Data.rate = rate;
		}
		
		if (voltage != m_Data.voltage) {
			noupdate = false;
			m_Data.voltage = voltage;
		}
		//fprintf(stderr,"new status=%d old =%d",status,m_Data.status);
		if (status != m_Data.status) {
			noupdate = false;
			m_Data.status = status;
			statusUpdated=true; //alex
		}
		
		if (fullCapacity != m_Data.fullCapacity) {
			noupdate = false;
			m_Data.fullCapacity = fullCapacity;
		}
		
		if (designCapacity != m_Data.designCapacity) {
			noupdate = false;
			m_Data.designCapacity = designCapacity;
		}
		
		if (currentCapacity != m_Data.currentCapacity) {
			noupdate = false;
			m_Data.currentCapacity = currentCapacity;
		}
		
		if (noupdate)
			return;
		
		qint8 newRelativeCharge = calcRelativeDef(currentCapacity, fullCapacity);
		
		if (newRelativeCharge != m_Data.relativeCharge || statusUpdated) { //alex: add status check
			m_Data.relativeCharge = newRelativeCharge;
			
			if (isVisible())
				updateIcon();
		}
		
		if (isVisible())
			updateToolTip();
	}
	
	void CBatteryIcon::updateData() {
		int currentCapacity = 0;
		int fullCapacity = 0;
		int designCapacity = 0;
		int rate = 0;
		int voltage = 0;
		int status = 0;
		bool energyUnits = sysfsDir.exists(m_Data.name + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
		
		rate = readIntSysFile(sysfsDir.filePath(m_Data.name + "/current_now").toLatin1().constData());
		voltage = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_NOW(UI_CAPTION_VOLTAGE)).toLatin1().constData()) / 10000;
		
		char buffer[BUF_SIZE];
		readStringFromFile(buffer, sysfsDir.filePath(m_Data.name + "/status").toLatin1().constData());
		status = toStatusInt(buffer);
		//fprintf(stderr,"status=%d\n",status);
		if (energyUnits) {
			fullCapacity    = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toLatin1().constData());
			designCapacity  = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toLatin1().constData());
			currentCapacity = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toLatin1().constData());
		}
		else {
			fullCapacity    = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_FULL(UI_CAPTION_CHARGE)).toLatin1().constData());
			designCapacity  = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_DESIGN(UI_CAPTION_CHARGE)).toLatin1().constData());
			currentCapacity = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_NOW(UI_CAPTION_CHARGE)).toLatin1().constData());
			int capacityProbe  = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_CAPACITY).toLatin1().constData());
			if (fullCapacity==0 ) //alex
			{
			  currentCapacity = readIntSysFile(sysfsDir.filePath(m_Data.name + UI_CAPTION_CAPACITY).toLatin1().constData());
			  fullCapacity=100;
			}
			else if (capacityProbe<=100) //alex: kernel 3.4 on sony tablet z: 'capacity' field in percents, current capacity iws smth wrong
			{
			  currentCapacity =  fullCapacity * capacityProbe / 100;
			}
		}
		updateData(currentCapacity, fullCapacity, designCapacity, rate, voltage, status, energyUnits);
	}
	
	void CBatteryIcon::setMessage(QString value) {
		m_Message = value;
		setToolTip(m_Message);
	}
	
	void CBatteryIcon::handleClicks(QSystemTrayIcon::ActivationReason reason) {
		switch (reason) {
			case Trigger:
				if (supportsMessages())
					showMessage(tr("Battery information"), m_Message);
				else
					QMessageBox::information(NULL, tr("Battery information"), m_Message);
				break;
			default:
				break;
		}
	}
}
