/*
 * Rotate an image 180° in O(log Dx + log Dy)
 * draw calls, using an extra buffer the same size
 * as the image.
 *
 * The basic concept is that you can invert an array by
 * inverting the top half, inverting the bottom half, and
 * then swapping them.
 * 
 * This is usually overkill, but it speeds up slow remote
 * connections quite a bit.
 */

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include "page.h"

int ndraw = 0;

enum {
	Xaxis,
	Yaxis,
};

static void reverse(Image*, Image*, int);
static void shuffle(Image*, Image*, int, int, Image*, int, int);
static void writefile(char *name, Image *im, int gran);
static void halvemaskdim(Image*);
static void swapranges(Image*, Image*, int, int, int, int);

/*
 * Rotate the image 180° by reflecting first
 * along the X axis, and then along the Y axis.
 */
void
rot180(Image *img)
{
	Image *tmp;

	tmp = xallocimage(display, img->r, img->chan, 0, DNofill);
	if(tmp == nil)
		return;

	reverse(img, tmp, Xaxis);
	reverse(img, tmp, Yaxis);

	freeimage(tmp);
}

Image *mtmp;

static void
reverse(Image *img, Image *tmp, int axis)
{
	Image *mask;
	Rectangle r;
	int i, d;

	/*
	 * We start by swapping large chunks at a time.
	 * The chunk size should be the largest power of
	 * two that fits in the dimension.
	 */
	d = axis==Xaxis ? Dx(img) : Dy(img);
	for(i = 1; i*2 <= d; i *= 2)
		;

	r = axis==Xaxis ? Rect(0,0, i,100) : Rect(0,0, 100,i);
	mask = xallocimage(display, r, GREY1, 1, DTransparent);
	mtmp = xallocimage(display, r, GREY1, 1, DTransparent);

	/*
	 * Now color the bottom (or left) half of the mask opaque.
	 */
	if(axis==Xaxis)
		r.max.x /= 2;
	else
		r.max.y /= 2;

	draw(mask, r, display->opaque, nil, ZP);
	writefile("mask", mask, i);

	/*
	 * Shuffle will recur, shuffling the pieces as necessary
	 * and making the mask a finer and finer grating.
	 */
	shuffle(img, tmp, axis, d, mask, i, 0);

	freeimage(mask);
}

/*
 * Shuffle the image by swapping pieces of size maskdim.
 */
static void
shuffle(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim)
{
	int slop;

	if(maskdim == 0)
		return;

	/*
	 * Figure out how much will be left over that needs to be
	 * shifted specially to the bottom.
	 */
	slop = imgdim % maskdim;

	/*
	 * Swap adjacent grating lines as per mask.
	 */
	swapadjacent(img, tmp, axis, imgdim - slop, mask, maskdim);

	/*
	 * Calculate the mask with gratings half as wide and recur.
	 */
	halvemaskdim(mask, maskdim, axis);
	writefile("mask", mask, maskdim/2);

	shuffle(img, tmp, axis, imgdim, mask, maskdim/2);

	/*
	 * Move the slop down to the bottom of the image.
	 */
	swapranges(img, tmp, 0, imgdim-slop, imgdim, axis);
	moveup(im, tmp, lastnn, nn, n, axis);
}

/*
 * Halve the grating period in the mask.
 * The grating currently looks like 
 * ####____####____####____####____
 * where #### is opacity.
 *
 * We want
 * ##__##__##__##__##__##__##__##__
 * which is achieved by shifting the mask
 * and drawing on itself through itself.
 * Draw doesn't actually allow this, so 
 * we have to copy it first.
 *
 *     ####____####____####____####____ (dst)
 * +   ____####____####____####____#### (src)
 * in  __####____####____####____####__ (mask)
 * ===========================================
 *     ##__##__##__##__##__##__##__##__
 */
static void
halvemaskdim(Image *m, int maskdim, int axis)
{
	Point δ;

	δ = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim);
	draw(mtmp, mtmp->r, mask, nil, mask->r.min);
	gendraw(mask, mask->r, mtmp, δ, mtmp, divpt(δ,2));
	writefile("mask", mask, maskdim/2);
}

/*
 * Swap the regions [a,b] and [b,c]
 */
static void
swapranges(Image *img, Image *tmp, int a, int b, int c, int axis)
{
	Rectangle r;
	Point δ;

	if(a == b || b == c)
		return;

	writefile("swap", img, 0);
	draw(tmp, tmp->r, im, nil, im->r.min);

	/* [a,a+(c-b)] gets [b,c] */
	r = img->r;
	if(axis==Xaxis){
		δ = Pt(1,0);
		r.min.x = img->r.min.x + a;
		r.max.x = img->r.min.x + a + (c-b);
	}else{
		δ = Pt(0,1);
		r.min.y = img->r.min.y + a;
		r.max.y = img->r.min.y + a + (c-b);
	}
	draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, b)));

	/* [a+(c-b), c] gets [a,b] */
	r = img->r;
	if(axis==Xaxis){
		r.min.x = img->r.min.x + a + (c-b);
		r.max.x = img->r.min.x + c;
	}else{
		r.min.y = img->r.min.y + a + (c-b);
		r.max.y = img->r.min.y + c;
	}
	draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, a)));
	writefile("swap", img, 1);
}

/*
 * Swap adjacent regions as specified by the grating.
 * We do this by copying the image through the mask twice,
 * once aligned with the grading and once 180° out of phase.
 */
static void
swapadjacent(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim)
{
	Point δ;
	Rectangle r0, r1;

	δ = axis==Xaxis ? Pt(1,0) : Pt(0,1);

	r0 = img->r;
	r1 = img->r;
	switch(axis){
	case Xaxis:
		r0.max.x = imgdim;
		r1.min.x = imgdim;
		break;
	case Yaxis:
		r0.max.y = imgdim;
		r1.min.y = imgdim;
	}

	/*
	 * r0 is the lower rectangle, while r1 is the upper one.
	 */
	draw(tmp, tmp->r, img, nil, 
}

void
interlace(Image *im, Image *tmp, int axis, int n, Image *mask, int gran)
{
	Point p0, p1;
	Rectangle r0, r1;

	r0 = im->r;
	r1 = im->r;
	switch(axis) {
	case Xaxis:
		r0.max.x = n;
		r1.min.x = n;
		p0 = (Point){gran, 0};
		p1 = (Point){-gran, 0};
		break;
	case Yaxis:
		r0.max.y = n;
		r1.min.y = n;
		p0 = (Point){0, gran};
		p1 = (Point){0, -gran};
		break;
	}

	draw(tmp, im->r, im, display->black, im->r.min);
	gendraw(im, r0, tmp, p0, mask, mask->r.min);
	gendraw(im, r0, tmp, p1, mask, p1);
}


static void
writefile(char *name, Image *im, int gran)
{
	static int c = 100;
	int fd;
	char buf[200];

	snprint(buf, sizeof buf, "%d%s%d", c++, name, gran);
	fd = create(buf, OWRITE, 0666);
	if(fd < 0)
		return;	
	writeimage(fd, im, 0);
	close(fd);
}

