#include "canvasview.h"
#include <qtimer.h>

#define TILESIZE 64

CanvasView::CanvasView(QWidget* parent, const char* name) : QCanvasView(parent, name) {
	setCanvas(new QCanvas(this));
	m_tileToProcess = 0;
	m_lastTable.resize(256);
	m_tileTimer = new QTimer(this);
	connect(m_tileTimer, SIGNAL(timeout()), this, SLOT(processOneTile()));
}

void CanvasView::loadImage(const QString & filename) {
	if (m_imagesize.isValid()) {
		closeImage();
	}

	m_filename = filename;
	QImage img(filename);
	m_imagesize = img.size();

	m_tilesx = img.width() / TILESIZE + ((img.width() % TILESIZE) ? 1 : 0);
	m_tilesy = img.height() / TILESIZE + ((img.height() % TILESIZE) ? 1 : 0);

	canvas()->resize(img.width(), img.height());
	m_sprites.resize(m_tilesx * m_tilesy, 0);
	m_tiles.resize(m_tilesx * m_tilesy, QImage());
	m_sequences.resize(m_tilesx * m_tilesy);
	
	for (int y = 0; y < m_tilesy; ++y) {
		for (int x = 0; x < m_tilesx; ++x) {
			m_tiles.at(y * m_tilesx + x) = img.copy(TILESIZE * x, TILESIZE * y, TILESIZE, TILESIZE);
				
			QValueList<QPixmap> sequence;
			QPixmap px;
			px.convertFromImage(m_tiles[y * m_tilesx + x]);
			sequence.push_back(px);
			m_sequences[y * m_tilesx + x] = new QCanvasPixmapArray(sequence);
			QCanvasSprite* spr = new QCanvasSprite(m_sequences[y * m_tilesx + x], canvas());
			spr->move(TILESIZE * x, TILESIZE * y);
			spr->show();
			m_sprites.at(y * m_tilesx + x) = spr;
		}
	}
	canvas()->update();
}

void CanvasView::saveImage() {
	QImage img(m_imagesize,32);
	for (int y = 0; y < m_tilesy; ++y) {
		for (int x = 0; x < m_tilesx; ++x) {
			bitBlt(&img, x * TILESIZE, y * TILESIZE, &m_tiles.at(y * m_tilesx + x));
		}
	}
	img.save(m_filename, "PNG");
}

void CanvasView::closeImage() {
	for (int y = 0; y < m_tilesy; ++y) {
		for (int x = 0; x < m_tilesx; ++x) {
			delete m_sprites[y * m_tilesx + x];
			delete m_sequences[y * m_tilesx + x];
		}
	}
	m_sprites.resize(0);
	m_sequences.resize(0);
	m_tiles.resize(0);
	m_tilesx = 0;
	m_tilesy = 0;
	m_imagesize = QSize(0,0);
	m_filename = "";
	canvas()->resize(0,0);
	canvas()->update();
}


void CanvasView::applyCurve(std::valarray<int> curve) {
	m_lastTable = curve;
	m_tileToProcess = 0;
	m_tileTimer->start(0);
}

void CanvasView::commit() {
	for (unsigned int i = 0; i < m_tiles.size(); ++i) {
		for (int y = 0; y < TILESIZE; ++y) {
			for (int x = 0; x < TILESIZE; ++x) {
				QRgb pixel = m_tiles[i].pixel(x,y);
				m_tiles[i].setPixel(x,y, qRgb(
						m_lastTable[qRed(pixel)],
						m_lastTable[qGreen(pixel)],
						m_lastTable[qBlue(pixel)]
				));
			}
		}
	}
}
	
void CanvasView::rollback() {
	for (unsigned int i = 0; i < m_tiles.size(); ++i) {
		m_sequences[i]->setImage(0, new QCanvasPixmap(m_tiles[i]));
		m_sprites[i]->setSequence(m_sequences[i]);
		canvas()->update();
	}
}

void CanvasView::setFileName(const QString & filename) {
	m_filename = filename;
}

void CanvasView::processOneTile() {
	QImage timg(TILESIZE,TILESIZE,32);
	for (int y = 0; y < TILESIZE; ++y) {
		for (int x = 0; x < TILESIZE; ++x) {
			QRgb pixel = m_tiles[m_tileToProcess].pixel(x,y);
			timg.setPixel(x,y, qRgb(
				m_lastTable[qRed(pixel)],
				m_lastTable[qGreen(pixel)],
				m_lastTable[qBlue(pixel)]
			));
		}
	}
	m_sequences[m_tileToProcess]->setImage(0, new QCanvasPixmap(timg));
	m_sprites[m_tileToProcess]->setSequence(m_sequences[m_tileToProcess]);
	canvas()->update();
	++m_tileToProcess;
	if (m_tileToProcess == m_tiles.size()) {
		m_tileTimer->stop();
	}
}
