#include <stdio.h>

#include <qcolor.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qbitmap.h>
#include <qrect.h>
#include <qstring.h>
#include <qwmatrix.h>

#include <kapp.h>
#include <kglobal.h>
#include <kstddirs.h>
#include <kiconloader.h>

#include "pixServer.h"
#include "board.h"
#include <klocale.h>
#include <kconfig.h>

//from the QColor man page.
QPixmap loadPixmap( const QString &fileName )
{
    return QPixmap(fileName);
}

PixServer::PixServer( Board *b, QWidget *parent)
{
    board = b;
    initPixmaps();
    initBrickPixmap();
    initbackPixmaps();
    initRoomPixmap();
    w = parent;
}

void PixServer::erase(int pos)
{
    if (!board->isEmpty(pos))
	return;

    QRect rect = board->rect(pos);
    bitBlt( w, rect.x(), rect.y(), &backPix,
	    rect.x(), rect.y(), rect.width(), rect.height());
}

void PixServer::restore(int pos)
{
    QRect rect = board->rect(pos);
    bitBlt( w, rect.x(), rect.y(), &roomPix,
	    rect.x(), rect.y(), rect.width(), rect.height());
}

void PixServer::draw(int pos, PixMap pix, int i)
{
    QPixmap p;
    p.resize(BRICKSIZE, BRICKSIZE);

    QRect rect = board->rect(pos);

    if (! plainColor)
	bitBlt( &p, 0, 0, &backPix,
		rect.x(), rect.y(), rect.width(), rect.height());
    else
	p.fill(backgroundColor);

    switch (pix) {
    case SamyPix:        bitBlt(&p ,0,0, &samyPix[i]);
	break;
    case CompuSnakePix:  bitBlt(&p ,0,0, &compuSnakePix[i]);
	break;
    case ApplePix:       bitBlt(&p ,0,0, &applePix[i]);
	break;
    case BallPix:        bitBlt(&p ,0,0, &ballPix[i]);
	break;
    default:
	break;
    }

    bitBlt(w, rect.x(), rect.y(), &p);
}

void PixServer::initPixmaps()
{

    QPixmap pm = BarIcon("snake1");
    QImage qi = pm.convertToImage();
    qi=qi.smoothScale(BRICKSIZE*18,BRICKSIZE);
    pm.convertFromImage(qi,QPixmap::AvoidDither);
    for (int x = 0 ; x < 18; x++){
	compuSnakePix[x].resize(BRICKSIZE, BRICKSIZE);
	bitBlt(&compuSnakePix[x] ,0,0, &pm,x*BRICKSIZE, 0, BRICKSIZE, BRICKSIZE, Qt::CopyROP, TRUE);
	compuSnakePix[x].setMask(compuSnakePix[x].createHeuristicMask());
    }

    pm = BarIcon("snake2");
    qi = pm.convertToImage();
    qi=qi.smoothScale(BRICKSIZE*18,BRICKSIZE);
    pm.convertFromImage(qi,QPixmap::AvoidDither);
    for (int x = 0 ; x < 18; x++){
	samyPix[x].resize(BRICKSIZE, BRICKSIZE);
	bitBlt(&samyPix[x] ,0,0, &pm,x*BRICKSIZE, 0, BRICKSIZE, BRICKSIZE, Qt::CopyROP, TRUE);
	samyPix[x].setMask(samyPix[x].createHeuristicMask());
    }

    pm = BarIcon("ball");
    qi = pm.convertToImage();
    qi=qi.smoothScale(BRICKSIZE*4,BRICKSIZE);
    pm.convertFromImage(qi,QPixmap::AvoidDither);
    for (int x = 0 ; x < 4; x++){
	ballPix[x].resize(BRICKSIZE, BRICKSIZE);
	bitBlt(&ballPix[x] ,0,0, &pm,x*BRICKSIZE, 0, BRICKSIZE, BRICKSIZE, Qt::CopyROP, TRUE);
	ballPix[x].setMask(ballPix[x].createHeuristicMask());
    }

    pm = BarIcon("apples");
    qi = pm.convertToImage();
    qi=qi.smoothScale(BRICKSIZE*2,BRICKSIZE);
    pm.convertFromImage(qi,QPixmap::AvoidDither);
    for (int x = 0 ; x < 2; x++){
	applePix[x].resize(BRICKSIZE, BRICKSIZE);
	bitBlt(&applePix[x] ,0,0, &pm,x*BRICKSIZE, 0, BRICKSIZE, BRICKSIZE, Qt::CopyROP, TRUE);
	applePix[x].setMask(applePix[x].createHeuristicMask());
    }
}

void PixServer::initbackPixmaps()
{
    QString path;
    plainColor = FALSE;

    int red, green, blue;
    red = green = blue = 0;

    KConfig *conf = kapp->config();
    if(conf != NULL) {
	int i = conf->readNumEntry("Background", 2);
	if(i == 1) {
	    backgroundColor = conf->readColorEntry("BackgroundColor");
	    plainColor = TRUE;
	} else if(i == 2) {
	    path = locate("appdata", "backgrounds/Green_Carpet.xpm");
	    path = conf->readEntry("BackgroundPixmap", path );
	}
    }

    QPixmap PIXMAP;
    int pw, ph;

    backPix.resize(MAPWIDTH, MAPHEIGHT);

    if (! plainColor) {

	PIXMAP = loadPixmap(path);

	if (!PIXMAP.isNull()) {
	    pw = PIXMAP.width();
	    ph = PIXMAP.height();

	    for (int x = 0; x <= MAPWIDTH; x+=pw)
		for (int y = 0; y <= MAPHEIGHT; y+=ph)
		    bitBlt(&backPix, x, y, &PIXMAP);
	}
	else  {
	    printf("error loading background image :%s\n", path.latin1() );
	    backgroundColor = (QColor(red, green, blue));
	    plainColor = TRUE;
	}
    }
    if ( plainColor)
	backPix.fill(backgroundColor);

    backPix.resize(MAPWIDTH, MAPWIDTH );
}

void PixServer::initBrickPixmap()
{
    QPixmap pm = BarIcon("brick");
    if (pm.isNull()) {
	printf(i18n("error loading %1, aborting\n").arg("brick.xpm").ascii());
	kapp->quit();
    }
    int pw = pm.width();
    int ph = pm.height();

    offPix.resize(MAPWIDTH, MAPWIDTH );
    for (int x = 0; x <= MAPWIDTH; x+=pw)
	for (int y = 0; y <= MAPHEIGHT; y+=ph)
	    bitBlt(&offPix, x, y, &pm);
    offPix.resize(MAPWIDTH, MAPHEIGHT );
}

void PixServer::initRoomPixmap()
{
    QPainter paint;
    paint.scale(2,2);
    roomPix.resize(MAPWIDTH, MAPHEIGHT);
    bitBlt(&roomPix,0,0, &backPix);
    paint.begin(&roomPix);

    for (unsigned int x = 0; x < board->size(); x++) {
	if (board->isBrick(x))
	    drawBrick(&paint, x);
    }
    paint.end();
}

void PixServer::drawBrick(QPainter *p ,int i)
{
    QColor light("gray90");
    QColor dark("gray40");

    int topSq   = board->getNext(N, i);
    int botSq   = board->getNext(S, i);
    int rightSq = board->getNext(E ,i);
    int leftSq  = board->getNext(W, i);

    QRect rect = board->rect(i);

    int x = rect.x();
    int y = rect.y();

    int X = x;
    int Y = y;
    int width, height;
    int Width, Height;

    int highlight = 3;

    Width = Height = width = height = rect.width();


    p->fillRect(x, y, width, height, light);

    if(!board->isBrick(topSq))    {Y+=highlight; Height-=highlight;}
    if(!board->isBrick(leftSq))   {X+=highlight; Width-=highlight;}
    if(!board->isBrick(botSq))     Height-=highlight;
    if(!board->isBrick(rightSq))   Width-=highlight;

    QRect xyz(X,Y,Width,Height);

    bitBlt(&roomPix, xyz.x(), xyz.y(), &offPix,
	   xyz.x(), xyz.y(), xyz.width(), xyz.height());


    if (board->isBrick(topSq) && board->isBrick(rightSq)
	&& !board->isBrick(board->getNext(NE ,i)))
	p->fillRect(x+width-highlight, y, highlight, highlight, dark);

    if (board->isBrick(botSq) && board->isBrick(rightSq)
	&& !board->isBrick(board->getNext(SE, i)))
	p->fillRect(x+width -highlight, y+height-highlight, highlight, highlight, dark);

    if (board->isBrick(topSq) && board->isBrick(leftSq)
	&& !board->isBrick(board->getNext(NW, i)))
	p->fillRect(x, y, highlight, highlight, light);

    if (board->isBrick(leftSq) && board->isBrick(botSq)
	&& !board->isBrick(board->getNext(SW ,i)))
	p->fillRect(x, y+height-highlight, highlight, highlight, light);


    QBrush brush( dark);
    p->setBrush(brush);
    p->setPen(Qt::NoPen);

    QPointArray a;

    if(!board->isBrick(topSq) && !board->isBrick(rightSq)){
	a.setPoints( 4,
		     x+width-highlight, y+height-1,
		     x+width-1, y+height-1,
		     x+width-1, y+1,
		     x+width-highlight, y+highlight);
	p->drawPolygon(a);
    }
    else if(!board->isBrick(rightSq))
	p->fillRect(x + width -highlight, y, highlight, height, dark);

    if(!board->isBrick(leftSq) && !board->isBrick(botSq)){
	a.setPoints( 4,
		     x+width-1, y+height-highlight,
		     x+width-1, y+height-1,
		     x+1, y+height-1,
		     x+highlight, y+height-highlight);
	p->drawPolygon(a);
    }
    else if(!board->isBrick(botSq))
	p->fillRect(x , y+height-highlight, width, highlight, dark);
}
