#include "main.h"
#include "picview.h"

#include "kpuzzleapp.h"
#include "kpuzzlewidget.h"

#include <qpainter.h>
#include <qwmatrix.h>
#include <qpen.h>
#include <qcolor.h>

CPicview::CPicview(QWidget* parent) : QWidget(parent)
{
	_pixmap = NULL;
	setMouseTracking(false);
	setBackgroundMode(NoBackground);
	_vRectTopLeft = QPoint(0,0);
}

CPicview::~CPicview()
{
	if (_pixmap) delete _pixmap;
}

void CPicview::paintEvent(QPaintEvent* e)
{
	if (_pixmap == NULL) return;
	ASSERT(_pixmap->size() == this->size());
	bitBlt(this,0,0,_pixmap,0,0,_pixmap->width(),_pixmap->height());
	QPainter pt(this);
	QPen pen(QColor(255,255,255),2,DashLine);
	pt.setPen(pen);
	pt.drawRect(vRect());
}

void CPicview::mouseMoveEvent(QMouseEvent* e)
{
	QPoint pos = DPtoLP(e->pos());
	QRect udRect(pos,_vRectSize);
	udRect = udRect.unite(vRect());
	_vRectTopLeft = pos;
	emit sigChangeViewPos(translate2GamePixmap(_vRectTopLeft));
	update(udRect);
}

void CPicview::mousePressEvent(QMouseEvent* e)
{
	QPoint pos = DPtoLP(e->pos());
	QRect udRect(pos,_vRectSize);
	udRect = udRect.unite(vRect());
	_vRectTopLeft = pos;
	emit sigChangeViewPos(translate2GamePixmap(_vRectTopLeft));
	update(udRect);
}

void CPicview::mouseReleaseEvent(QMouseEvent* e)
{

}
	
QPoint CPicview::DPtoLP(QPoint p)
{
	// Mouse click is always the middle of a rectangle
	p.setX(p.x() - _vRectSize.width() / 2);
	if (p.x() < 0) p.setX(0);
	if (size().width() - p.x() < _vRectSize.width()) 
		p.setX(size().width() - _vRectSize.width());

	p.setY(p.y() - _vRectSize.height() / 2);
	if (p.y() < 0) p.setY(0);
	if (size().height() - p.y() < _vRectSize.height()) 
		p.setY(size().height() - _vRectSize.height());
	
	return p;
}

void CPicview::updatePixmap(QPixmap* p,QRect udRect)
{
	if (p) {
		QWMatrix sc;
		sc.scale(PICVIEW_WIDTH / p->width(),
			 PICVIEW_HEIGHT / p->height());

		if (!_pixmap) _pixmap = new QPixmap;
		*_pixmap = p->xForm(sc);

		_vRectSize = this->size();

		int newWidth = (int) (_vRectSize.width() * 
			((float) VISIBLE_PIXMAP_SIZE / p->width()));
		if (newWidth < this->width()) // Rectangle must be shown
			_vRectSize.setWidth(newWidth);		

		int newHeight = (int) (_vRectSize.height() * 
			((float) VISIBLE_PIXMAP_SIZE / p->height()));
		if (newHeight < this->height()) // Rectangle must be shown
			_vRectSize.setHeight(newHeight);		

		_gamePixmapSize = p->size();
	}
	update(udRect);
}

void CPicview::addPiece(QPixmap* piece,QPoint pos)
{
	QWMatrix sc;
	sc.scale(scaleX(),scaleY());
	QPixmap np = piece->xForm(sc);
	QSize realPieceSize = ((KPuzzleWidget*) parentWidget())->game()->pieceSize();
	int displace = ((KPuzzleWidget*) parentWidget())->game()->displace();
	float pieceWidth = realPieceSize.width() * scaleX();
	float pieceHeight = realPieceSize.height() * scaleY();
	QPoint newPos((int) (pos.x() * pieceWidth - displace * scaleX()),
		      (int) (pos.y() * pieceHeight - displace * scaleY()));
	ASSERT(newPos.x() >= 0);
	ASSERT(newPos.y() >= 0);
	
	bitBlt(_pixmap,newPos,&np,np.rect(),CopyROP,false);
	update(QRect(newPos,np.size()));
}

void CPicview::slotChangeViewPos(QPoint pos)
{
	_vRectTopLeft = translateFromGamePixmap(pos);
	update();
}

QPoint CPicview::translate2GamePixmap(QPoint p)
{
	float x = (float) p.x() / size().width();
	float y = (float) p.y() / size().height();

	QPoint res((int) (x * gamePixmapSize().width()),
		   (int) (y * gamePixmapSize().height()));
	return res;
}

QPoint CPicview::translateFromGamePixmap(QPoint p)
{
	float x = (float) p.x() / gamePixmapSize().width();
	float y = (float) p.y() / gamePixmapSize().height();

	QPoint res((int) (x * size().width()),(int) (y * size().height()));
	return res;
}
