/*
 * daemondock.cpp
 * Copyright (C) 1999 Paul Campbell <paul@taniwha.com>
 *
 * This file contains the docked widget for the laptop battery monitor
 *
 * $Id: daemondock.cpp,v 1.18 2001/07/24 08:55:55 campbell Exp $
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <qtooltip.h>    
#include <kapp.h>
#include <stdio.h>
#include <stdlib.h>

#include <klocale.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <kpopupmenu.h>
#include <dcopclient.h>
#include <kstddirs.h>
#include "kpcmcia.h"
#include "kpcmciainfo.h"
#include "daemondock.h"
#include "portable.h"
#include <iostream.h>

laptop_dock::laptop_dock( laptop_daemon* parent)
  : KDockWindow()
{

    _pcmcia = NULL;
    p = parent;
    current_code = -1;
      // popup menu for right mouse button
    QPopupMenu* popup = contextMenu();

    int can_standby = laptop_portable::has_standby();
    int can_suspend = laptop_portable::has_suspend();
    int can_hibernate = laptop_portable::has_hibernation();
    popup->insertItem(i18n("Setup..."), this, SLOT(invokeSetup()));
    if (can_standby || can_suspend || can_hibernate) {
    	popup->insertSeparator();
    	if (can_standby) popup->insertItem(i18n("Standby..."), this, SLOT(invokeStandby()));
	if (can_suspend) popup->insertItem(i18n("&Lock && Suspend..."), this, SLOT(invokeLockSuspend()));
    	if (can_suspend) popup->insertItem(i18n("&Suspend..."), this, SLOT(invokeSuspend()));
        if (can_hibernate) popup->insertItem(i18n("&Lock && Hibernate..."), this, SLOT(invokeLockHibernation()));
	if (can_hibernate) popup->insertItem(i18n("&Hibernate..."), this, SLOT(invokeHibernation()));
    }
}


void laptop_dock::slotEjectAction(int id) {
KPCMCIACard *f = NULL;
  f = _ejectActions[id];

  if (f) f->eject();
}


void laptop_dock::slotSuspendAction(int id) {
KPCMCIACard *f = NULL;
  f = _suspendActions[id];

  if (f) f->suspend();
}


void laptop_dock::slotResumeAction(int id) {
KPCMCIACard *f = NULL;
  f = _resumeActions[id];

  if (f) f->resume();
}


void laptop_dock::slotResetAction(int id) {
KPCMCIACard *f = NULL;
  f = _resetActions[id];

  if (f) f->reset();
}


void laptop_dock::slotInsertAction(int id) {
KPCMCIACard *f = NULL;
  f = _insertActions[id];

  if (f) f->insert();
}


void laptop_dock::slotDisplayAction(int id) {
KPCMCIAInfo *f =  new KPCMCIAInfo(_pcmcia);
   f->showTab(_displayActions[id]->num());
}


void laptop_dock::noop()
{
}
void laptop_dock::mousePressEvent( QMouseEvent *event )
{
 	if(event->button() == LeftButton) {
		QPopupMenu *popup = new QPopupMenu(0, "popup");

		if (!p->exists) {
			popup->insertItem(i18n("Power Manager Not Found"), this, SLOT(noop()));
		} else {
			QString tmp;

			if (p->left < 0) {	// buggy BIOS
				tmp = i18n("%1% charged").arg(p->val);
			} else {
				QString num3; num3.setNum(p->left%60);
				num3 = num3.rightJustify(2, '0');
				tmp = i18n("%1:%2 minutes left").arg(p->left/60).arg(num3);
			}
			popup->insertItem(tmp, this, SLOT(noop()));
			popup->setItemEnabled(0, 0);
			popup->insertSeparator();
			if (p->powered) {
				popup->insertItem(i18n("Charging"), this, SLOT(noop()));
			} else {
				popup->insertItem(i18n("Not Charging"), this, SLOT(noop()));
			}
			popup->setItemEnabled(1, 0);
		}

                /**
                 *        ADD the PCMCIA entries here
                 */
                if (_pcmcia && _pcmcia->haveCardServices()) {
                   QString slotname = i18n("Slot %1"); // up here so we only construct it once
                   int id;
                   popup->insertSeparator();
                   _ejectActions.clear();
                   _resetActions.clear();
                   _insertActions.clear();
                   _suspendActions.clear();
                   _resumeActions.clear();
                   _displayActions.clear();
                   id = popup->insertItem(i18n("Card slots..."), this, SLOT(slotDisplayAction(int)));
                   _displayActions.insert(id, _pcmcia->getCard(0));
                   for (int i = 0; i < _pcmcia->getCardCount(); i++) {
                      KPCMCIACard *thiscard;
                      thiscard = _pcmcia->getCard(i);
                      if (thiscard && (thiscard->present())) {
                         QPopupMenu *thisSub = new QPopupMenu(popup, thiscard->name().latin1());
                         id = thisSub->insertItem(i18n("Details..."), this, SLOT(slotDisplayAction(int)));
                         _displayActions.insert(id, thiscard);

                         // add the actions
                         QPopupMenu *actionsSub = new QPopupMenu(thisSub, "actions");
                         id = actionsSub->insertItem(i18n("Eject"), this, SLOT(slotEjectAction(int)));
                         actionsSub->setItemEnabled(id, !(thiscard->status() & CARD_STATUS_BUSY));
                         _ejectActions.insert(id, thiscard);
                         id = actionsSub->insertItem(i18n("Suspend"), this, SLOT(slotSuspendAction(int)));
                         actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_SUSPEND|CARD_STATUS_BUSY)));
                         _suspendActions.insert(id, thiscard);
                         id = actionsSub->insertItem(i18n("Resume"), this, SLOT(slotResumeAction(int)));
                         actionsSub->setItemEnabled(id, (thiscard->status() & CARD_STATUS_SUSPEND));
                         _resumeActions.insert(id, thiscard);
                         id = actionsSub->insertItem(i18n("Reset"), this, SLOT(slotResetAction(int)));
                         _resetActions.insert(id, thiscard);
                         id = actionsSub->insertItem(i18n("Insert"), this, SLOT(slotInsertAction(int)));
                         _insertActions.insert(id, thiscard);
                         actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND)));
                         thisSub->insertItem(i18n("Actions"), actionsSub);

                         // add a few bits of information
                         thisSub->insertSeparator();
                         thisSub->insertItem(slotname.arg(thiscard->num()+1), this, SLOT(noop()));
                         if (thiscard->status() & CARD_STATUS_READY)
                            thisSub->insertItem(i18n("Ready"), this, SLOT(noop()));
                         if (thiscard->status() & CARD_STATUS_BUSY)
                            thisSub->insertItem(i18n("Busy"), this, SLOT(noop()));
                         if (thiscard->status() & CARD_STATUS_SUSPEND)
                            thisSub->insertItem(i18n("Suspended"), this, SLOT(noop()));
                         popup->insertItem(thiscard->name(), thisSub);
                      }
                   }
                }
	
		popup->popup(QCursor::pos());
	}
	
}
void laptop_dock::mouseReleaseEvent( QMouseEvent *e )
{
    if ( !rect().contains( e->pos() ) )
        return;
 
    switch ( e->button() ) {
    case LeftButton:
        break;
    case MidButton:
        // fall through
    case RightButton:
	{
		KPopupMenu *menu = contextMenu();
        	contextMenuAboutToShow( menu );
        	menu->popup( e->globalPos() );
	}
        break;
    default:
        // nothing
        break;
    }                   
}
void laptop_dock::showEvent( QShowEvent * )
{

}
void laptop_dock::invokeHibernation()
{
        laptop_portable::invoke_hibernation();
}

void laptop_dock::invokeLockHibernation()
{
  DCOPClient* client = kapp->dcopClient();
  if (client)
    {
      client->attach();
      client->send("kdesktop", "KScreensaverIface", "lock()", "");
      client->detach();
    }
  laptop_portable::invoke_hibernation();
}
void laptop_dock::invokeStandby()
{
	laptop_portable::invoke_standby();
}

void laptop_dock::invokeSuspend()
{
	laptop_portable::invoke_suspend();
}

void laptop_dock::invokeLockSuspend()
{
  DCOPClient* client = kapp->dcopClient();
  if (client)
    {
      client->attach();
      client->send("kdesktop", "KScreensaverIface", "lock()", "");
      client->detach();
    }
  laptop_portable::invoke_suspend();
}

void laptop_dock::invokeSetup()
{
	::system("kcmshell PowerControl/battery&");
}

laptop_dock::~laptop_dock() {
}
                                      

void laptop_dock::displayPixmap()
{
	int new_code;

	if (!p->exists)
		new_code = 1;
	else if (!p->powered)
		new_code = 2;
	else
		new_code = 3;

	if (current_code != new_code) {
		current_code = new_code;

		// we will try to deduce the pixmap (or gif) name now.  it will
		// vary depending on the dock and power
		QString pixmap_name, mini_pixmap_name;
	
		if (!p->exists)
			pixmap_name = p->noBatteryIcon;
		else if (!p->powered)
			pixmap_name = p->noChargeIcon;
		else
			pixmap_name = p->chargeIcon;

		pm = SmallIcon(pixmap_name, 20);
	}

	// at this point, we have the file to display.  so display it

	QImage image = pm.convertToImage();

	int w = image.width();
	int h = image.height();
	int count = 0;
	QRgb rgb;
	int x, y;
	for (x = 0; x < w; x++)
	for (y = 0; y < h; y++) {
		rgb = image.pixel(x, y);
		if (qRed(rgb) == 0xff &&
		    qGreen(rgb) == 0xff &&
		    qBlue(rgb) == 0xff)
			count++;
	}
	int c = (count*p->val)/100;
	if (p->val == 100) {
		c = count;
	} else
	if (p->val != 100 && c == count)
		c = count-1;

	
	if (c) {
		uint ui;
		QRgb blue = qRgb(0x00,0x00,0xff);

		if (image.depth() <= 8) {
			ui = image.numColors();		// this fix thanks to Sven Krumpke
			image.setNumColors(ui+1);
			image.setColor(ui, blue);
		} else {
			ui = 0xff000000|blue;
		}
	
		for (y = h-1; y >= 0; y--) 
		for (x = 0; x < w; x++) {
			rgb = image.pixel(x, y);
			if (qRed(rgb) == 0xff &&
		    	    qGreen(rgb) == 0xff &&
		    	    qBlue(rgb) == 0xff) {
				image.setPixel(x, y, ui);
				c--;
				if (c <= 0)
					goto quit;
			}
		}
	}
quit:

	QPixmap q;
	q.convertFromImage(image);
	setPixmap(q);
	adjustSize();

	QString tmp;
	if (!p->exists) {
		tmp = i18n("Laptop Power Management not available");
	} else
	if (p->powered) {
		if (p->val == 100) {
			tmp = i18n("Plugged in - fully charged");;
		} else {
			if (p->left >= 0) {
				QString num3; num3.setNum(p->left%60);
				num3 = num3.rightJustify(2, '0');
				tmp = i18n("Plugged in - %1% charged (%2:%3 minutes)")
					.arg(p->val).arg(p->left/60).arg(num3);
			} else {
				tmp = i18n("Plugged in - %1% charged").arg(p->val);
			}
		}
	} else {
		if (p->left >= 0) {
			QString num3; num3.setNum(p->left%60);
			num3 = num3.rightJustify(2, '0');
			tmp = i18n("Running on batteries - %1% charged (%2:%3 minutes)")
					.arg(p->val).arg(p->left/60).arg(num3);
		} else {
			tmp = i18n("Running on batteries  - %1% charged").arg(p->val);
		}
	}
	QToolTip::add(this, tmp); 
}

#include "daemondock.moc"
