/***************************************************************************
 *   Copyright (C) 2004 by Stefano                                         *
 *   stefano@xiaprojects.com                                               *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "xeplugin_gepager.h"

#include <xeobject.h>
#include <xeconfiguration.h>
#include <xgdocker.h>
#include <kwin.h>
#include <krootpixmap.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kwinmodule.h>
#include <kwin.h>
#include <netwm.h>

#include <qpainter.h>
#include <qdrawutil.h>
#include <qlineedit.h>
#include <qbitmap.h>
#include <dcopclient.h>

XEPlugin_GEPager::XEPlugin_GEPager(QWidget *parent, const char *name)
 : QWidget(0, name)
{
	XEObject::xPluginAdd(this);
	KWin::setType(winId(), NET::Dock);
	setBackgroundMode(Qt::NoBackground,Qt::NoBackground);
	NETWinInfo* info;
	info = new NETWinInfo( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMState );
	info->setDesktop( NETWinInfo::OnAllDesktops);
	
	nRows=2;
	desktopPreview=1;
	//qWarning("XEPlugin_GEPager::XEPlugin_GEPager(QWidget *parent, const char *name)");
	
	paintBuffer.resize(1,1);
	paintBuffer.fill(Qt::black);
	pixmapBackground.resize(1,1);
	pixmapBackground.fill(Qt::black);
}


XEPlugin_GEPager::~XEPlugin_GEPager()
{
	//qWarning("XEPlugin_GEPager::~XEPlugin_GEPager()");
}


#include "xeplugin_gepager.moc"


/*!
    \fn XEPlugin_GEPager::xStop()
 */
void XEPlugin_GEPager::xStop()
{
    /// @todo implement me
	//qWarning("void XEPlugin_GEPager::xStop()");
}


/*!
    \fn XEPlugin_GEPager::xSetup()
 */
void XEPlugin_GEPager::xSetup()
{
#ifndef ENABLE_FINAL
	qWarning("void XEPlugin_GEPager::xSetup()");
#endif
	XEConfiguration *Configurator=(XEConfiguration *)XEObject::xGetConfiguration();
	xGDocker=(XGDocker *)XEObject::xGetDocker();
	if(Configurator==NULL || xGDocker==NULL)
	{
#ifndef ENABLE_FINAL
	// Emits Signal of warning
	//xWarningMsg(this,"error while searching for plugin");
	qWarning("error while searching for plugin");
#endif
		return;
	}
	ActiveConfiguration=Configurator->xGetConfiguration();
	
	
	KDesktopBackground=new KRootPixmap((QWidget*)this);
	connect(KDesktopBackground, 
		SIGNAL(backgroundUpdated(const QPixmap &)), 
		this, SLOT(backgroundUpdated(const QPixmap &)));
	
	KDesktopBackground->setCustomPainting(true);
	
	vd[0].load(::locate("data","kxdocker/themes/bar/virtual_desktop.png"));
	vd[1].load(::locate("data","kxdocker/themes/bar/virtual_desktop_active.png"));
	if(vd[0].isNull())
	{
		QImage TBuffer;
		// we cannot load the pillow than we create a fully transparent image
		TBuffer.create(
			24,
			21,
			32);
		TBuffer.setAlphaBuffer(false);
		TBuffer.fill(0);
		TBuffer.setAlphaBuffer(true);
		vd[0].convertFromImage(TBuffer);
		vd[0].detach();
	}
	if(vd[1].isNull())
	{
		QImage TBuffer;
		// we cannot load the pillow than we create a fully transparent image
		TBuffer.create(
			24,
			21,
			32);
		TBuffer.setAlphaBuffer(false);
		TBuffer.fill(0);
		TBuffer.setAlphaBuffer(true);
		vd[1].convertFromImage(TBuffer);
		vd[1].detach();
	}
	// loading XML Configurations
	for(int i=0;i<ActiveConfiguration->Plugins.Plugin.count(); i++)
	{
		if(ActiveConfiguration->Plugins.Plugin.at(i)->Info.Name=="GEPager")
		{
			if(ActiveConfiguration->Plugins.Plugin.at(i)->xmlConfiguration.count())
			{
			xSetupParameter("desktopPreview",
			ActiveConfiguration->Plugins.Plugin.at(i)->xmlConfiguration.item(0).toElement().attribute("desktopPreview"));
			// Only 1 configuration
			}
			else
			{
		// Ok, You don't have specified the xml configuration, we have to create it!!
			
			// Creating fake document
			QDomDocument 	doc( "KXDocker_Conf" );
			// the fake root
			QDomElement fakeRoot=doc.createElement("FakeRoot");
			// appending childs
			doc.appendChild(fakeRoot);
			// now creating the configuration
			QDomElement CreatingCfg=doc.createElement("pluginconf");
			// Ok this is a plugin Configuration
			QStringList	a;
			// Creating the Attributes via the standard plugin interface
			xGetParameterList(&a);
			for(int istoringXML=0;istoringXML<a.count();istoringXML++)
			{
				QString returnValue;
				xGetParameter(a[istoringXML],returnValue);
				CreatingCfg.setAttribute(a[istoringXML],returnValue);
			}
			// Now appending to the configuration
			fakeRoot.appendChild(CreatingCfg);
			ActiveConfiguration->Plugins.Plugin.at(i)->xmlConfiguration=fakeRoot.childNodes();//fakeRoot.elementsByTagName("pluginconf");
			
			}
			break;
		}
	}
	
	
	KDEWM=new KWinModule();
    	active = KDEWM->activeWindow();
    	connect( KDEWM, SIGNAL( activeWindowChanged(WId)), SLOT( slotActiveWindowChanged(WId) ) );
    	connect( KDEWM, SIGNAL( windowAdded(WId) ), this, SLOT( slotWindowAdded(WId) ) );
    	connect( KDEWM, SIGNAL( windowRemoved(WId) ), this, SLOT( slotWindowRemoved(WId) ) );
    	connect( KDEWM, SIGNAL( windowChanged(WId,unsigned int) ), this, SLOT( slotWindowChanged(WId,unsigned int) ) );
    	connect( KDEWM, SIGNAL( stackingOrderChanged() ), this, SLOT( slotStackingOrderChanged() ) );

    for( QValueList<WId>::ConstIterator it = KDEWM->windows().begin();
	 it != KDEWM->windows().end();
	 ++it )
	slotWindowAdded( *it );
	connect( KDEWM,SIGNAL(currentDesktopChanged(int)), this,SLOT(currentDesktopChanged(int)) );
	
	nRows=ActiveConfiguration->Icons.Size/vd[0].height();
	if(nRows<1)nRows=1;
	int ncols=(KDEWM->numberOfDesktops()/nRows);
	if((KDEWM->numberOfDesktops()%nRows)>0)ncols++;
	
	paintBuffer.resize(vd[0].width()*ncols,vd[0].height()*nRows);
	resize(vd[0].width()*ncols,vd[0].height()*nRows);
	bgcolor=QColor(drand48()*256,drand48()*256,drand48()*256);
}


/*!
    \fn XEPlugin_GEPager::xStart()
 */
void XEPlugin_GEPager::xStart()
{
	//qWarning("void XEPlugin_GEPager::xStart()");
	connect(xGDocker,
	SIGNAL(xEventWidgetMoved(int,int,int,int,int,int)),
	this,
	SLOT(xEventWidgetMoved(int,int,int,int,int,int))
	);
	connect(xGDocker,
	SIGNAL(xEventDockerHidden()),
	this,
	SLOT(xEventDockerHidden())
	);
	connect(xGDocker,
	SIGNAL(xEventDockerShowed()),
	this,
	SLOT(xEventDockerShowed())
	);

	lastDesktop=KDEWM->currentDesktop();
	KDesktopBackground->start();
	xUpdate();
	//show();
	lower();
}


/*!
    \fn XEPlugin_GEPager::xEventWidgetMoved(int x,int y,int x0, int y0, int x1,int int y1)
 */
void XEPlugin_GEPager::xEventWidgetMoved(int x,int y,int x0, int y0, int x1,int y1)
{
	move(x+x1+ActiveConfiguration->Icons.Size*2+16,y+y1);
}


/*!
    \fn XEPlugin_GEPager::paintEvent( QPaintEvent *e)
 */
void XEPlugin_GEPager::paintEvent( QPaintEvent *e)
{
	//qWarning("void XEPlugin_GEPager::paintEvent( QPaintEvent *e)");
	QRect rect = e->rect();
	int l=rect.left();
	int t=rect.top();
	int w=rect.width();
	int h=rect.height();
	bitBlt(this,
		l,
		t,
		&paintBuffer,
		l,t,w,h,
		Qt::CopyROP);
	//bitBlt(this,0,0,&paintBuffer,0,Qt::CopyROP);
}


/*!
    \fn XEPlugin_GEPager::backgroundUpdated(const QPixmap &)
 */
void XEPlugin_GEPager::backgroundUpdated(const QPixmap &pb)
{
	pixmapBackground=pb;
	xUpdate();
	repaint();
}


/*!
    \fn XEPlugin_GEPager::xUpdate()
 */
void XEPlugin_GEPager::xUpdate()
{
	//qWarning("void XEPlugin_GEPager::xUpdate()");
	paintBuffer=pixmapBackground;
	int ncols=(KDEWM->numberOfDesktops()/nRows);
	if((KDEWM->numberOfDesktops()%nRows)>0)ncols++;
	int dy=0;
	int nd=0;
	int dx=0;
	
	for(int k=0;k<nRows;k++)
	{
		for(int i=0;i<ncols;i++)
		{
			dy=k*vd[0].height();
			dx=i*vd[0].width();
			if (desktopPreview) {
			QPixmap desk(paintDesktop(nd+1,vd[0].width(),vd[0].height(),lastDesktop==nd+1));
			bitBlt(&paintBuffer,dx,dy,&desk);
			} else {
			if(lastDesktop==nd+1) bitBlt(&paintBuffer,dx,dy,&vd[0]);
			else bitBlt(&paintBuffer,dx,dy,&vd[1]);
			}
			nd++;
			if(KDEWM->numberOfDesktops()<nd)return;
		}
	}
}


/*!
    \fn XEPlugin_GEPager::currentDesktopChanged(int)
 */
void XEPlugin_GEPager::currentDesktopChanged(int Desktop)
{
	if(lastDesktop!=Desktop)
	{
		lastDesktop=Desktop;
		xUpdate();
		bgcolor=QColor(drand48()*256,drand48()*256,drand48()*256);
	}
	repaint();
	
}


/*!
    \fn XEPlugin_GEPager::mouseReleaseEvent ( QMouseEvent * e )
 */
void XEPlugin_GEPager::mouseReleaseEvent ( QMouseEvent * e )
{
	/*
		DesktopNum=(x-self.PagerX)/self.ImageDeltaX
		if(y>self.PagerY+self.ImageDeltaY):
			# we are on the second line...
			DesktopNum=DesktopNum+(self.SecondRow)
		if(button==1):
			# left mouse
			self.SwitchDesktop(DesktopNum)
	
	*/
	int x=e->pos().x();
	int y=e->pos().y();
	int DesktopNum=x/vd[0].width();
	DesktopNum=DesktopNum+(y/vd[0].height())*KDEWM->numberOfDesktops()/nRows;
	
	if(e->button()==Qt::LeftButton)
	{
		KWin::setCurrentDesktop(DesktopNum+1);
	}
	lower();
}


/*!
    \fn XEPlugin_GEPager::xEventDockerHidden()
 */
void XEPlugin_GEPager::xEventDockerHidden()
{
	hide();
	//showMinimized();
}


/*!
    \fn XEPlugin_GEPager::xEventDockerShowed()
 */
void XEPlugin_GEPager::xEventDockerShowed()
{
	KWin::setOnAllDesktops(winId(),true);
	show();
	//showNormal();
	lower();
	//QTimer::singleShot(1,this,SLOT(preview()));
}


/*!
    \fn XEPlugin_GEPager::preview()
 */
void XEPlugin_GEPager::preview()
{
	NETWinInfo* info;
	info = new NETWinInfo( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMState );
	info->setDesktop( NETWinInfo::OnAllDesktops);
}

#ifdef FocusOut
#undef FocusOut
#endif

QPixmap XEPlugin_GEPager::paintDesktop(int deskNum, int width, int height,bool curr)
{
    QPainter p;
    QPixmap pf( width, height );
    int transparent=0;

    // the following breaks dark color schemes
    QBrush bg;
    if (curr) bg = QBrush(bgcolor);
    else bg =colorGroup().brush( QColorGroup::Base );
    //setBackgroundOrigin( AncestorOrigin );
    QColor fg =( transparent) ? colorGroup().base() : colorGroup().text();

    if ( desktopPreview ) {
	QPixmap pm( width - 2, height - 2 );
	QBitmap pmask( pm.size(), true /*clear*/ );
	//if (pm.isNull() || pmask.isNull()) return pm;
	QPainter pp( &pm, this  );
	QPainter pmaskp( &pmask );

	if( ! transparent )
	    pp.fillRect( pm.rect(), bg );
	pp.setPen(fg);
	int dw = QApplication::desktop()->width();
	int dh = QApplication::desktop()->height();
	QValueList<WId>::ConstIterator it;
	// SELI this needs checking for kwin_iii
	for ( it = KDEWM->stackingOrder().begin();
	      it != KDEWM->stackingOrder().end(); ++it )
        {
	    KWin::WindowInfo* info = this->info( *it );

	    if ( info &&
                 info->windowType( NET::NormalMask | NET::DesktopMask | NET::DockMask
	            | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask
	            | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask ) != NET::Desktop &&
                 !info->isMinimized() &&
                 (info->onAllDesktops() || info->desktop() == deskNum ) &&
                 !(info->state() & NET::SkipPager || info->state() & NET::Shaded ) )
            {
		QRect r =  info->frameGeometry();
		r = QRect( r.x() * pm.width() / dw, 2 + r.y() * pm.height() / dh,
			   r.width() * pm.width() / dw, r.height() * pm.height() / dh );
		if ( KDEWM->activeWindow() == (*it) ) {
		    qDrawShadeRect( &pp, r, colorGroup(), false, 1, 0, &colorGroup().brush( QColorGroup::Highlight ) );
		} else {
		    pp.fillRect( r, colorGroup().brush(  QColorGroup::Button ) );
		    qDrawShadeRect( &pp, r, colorGroup(), true, 1, 0 );
		}
		if( transparent )
		    pmaskp.fillRect( r, color1 );
	    }
	}
	pp.end();
	pmaskp.end();
	if( transparent )
	{
	    pm.setMask( pmask );
	    erase();
	}
	p.begin( &pf );
	p.drawPixmap( 1, 1, pm );
    } else {
	p.begin( &pf );
	if( ! transparent )
	    p.fillRect( rect(), bg );
    }

    p.setPen( fg );

    if( transparent )
	p.setRasterOp( XorROP );

    /* if ( pager()->mode() == XEPlugin_GEPager::LabelNumber ) {
	p.drawText(0, 0, width(), height(), AlignCenter, QString::number( deskNum ) );
    } else if ( pager()->mode() == XEPlugin_GEPager::LabelName ) {
	p.drawText( 0, 0, width(), height(), AlignVCenter | AlignCenter, pager()->kwin()->desktopName( deskNum ) );
    } */

    /* if(!isOn() && !isDown()){
	p.setPen(colorGroup().light());
	p.drawLine(0, 0, width()-1, 0);
	p.drawLine(0, 0, 0, height()-1);
	p.setPen(Qt::black);
	p.drawLine(0, height()-1, width()-1, height()-1);
	p.drawLine(width()-1, 0, width()-1, height()-1);
    } else */
    {
	p.drawRect(QRect(0,0,width,height));
    }
    p.end();
    return pf;
}


void XEPlugin_GEPager::slotActiveWindowChanged( WId win )
{
    if ( !desktopPreview )
	return;
    active = win;
	slotRefresh();
}

void XEPlugin_GEPager::slotWindowAdded( WId win)
{
    if ( !desktopPreview )
	return;
	slotRefresh();
}

void XEPlugin_GEPager::slotWindowRemoved( WId win )
{
    if ( !desktopPreview ) {
	windows.remove( win );
	return;
    }
    if (win == active)
        active = 0;

    windows.remove( (long) win );

	    slotRefresh();
}

void XEPlugin_GEPager::slotWindowChanged( WId win , unsigned int properties )
{
    if(( properties & ( NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMGeometry )) == 0 )
        return;
    if ( !desktopPreview ) {
	windows.remove( win );
	return;
    }
    windows.remove( (long) win );
	    slotRefresh();
}

KWin::WindowInfo* XEPlugin_GEPager::info( WId win )
{
    KWin::WindowInfo* info = windows[win];
    if (!info ) {
	info = new KWin::WindowInfo( win,
            NET::WMWindowType | NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMGeometry | NET::WMKDEFrameStrut, 0 );
	windows.insert( (long) win, info );
    }
    return info;
}

void XEPlugin_GEPager::slotStackingOrderChanged()
{
    if ( !desktopPreview )
	return;
    slotRefresh();
}

void XEPlugin_GEPager::slotRefresh()
{
	xUpdate();
	repaint();
}




/*!
    \fn XEPlugin_GEPager::xGetParameter(const QString vname, QString&vvalue)
 */
void XEPlugin_GEPager::xGetParameter(const QString vname, QString&vvalue)
{
	if(vname=="desktopPreview")vvalue.setNum(desktopPreview);
}


/*!
    \fn XEPlugin_GEPager::xSetupParameter(const QString vname, const QString vvalue)
 */
void XEPlugin_GEPager::xSetupParameter(const QString sName, const QString sValue)
{
	bool okRet=false;
	if(sName=="desktopPreview")
	{
		desktopPreview=sValue.toInt(&okRet);
		if(okRet==false)
		{
			desktopPreview=0;
		}
	}
	for(int i=0;i<ActiveConfiguration->Plugins.Plugin.count(); i++)
	{
		if(ActiveConfiguration->Plugins.Plugin.at(i)->Info.Name=="GEPager")
		{
		
		// update xml configuration
			ActiveConfiguration->Plugins.Plugin.at(i)->xmlConfiguration.item(0).toElement().setAttribute("desktopPreview",desktopPreview
			);
		}
	}	
}


/*!
    \fn XEPlugin_GEPager::xGetParameterList(QStringList *a)
 */
void XEPlugin_GEPager::xGetParameterList(QStringList *a)
{
	a->append("desktopPreview");
}
