#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <bio.h>
#include "imagefile.h"

#define	MAXLINE	70

/*
 * Write data
 */
static
char*
writedata(Biobuf *fd, Image *image, Memimage *memimage)
{
	char *err;
	uchar *data;
	int i, x, y, ndata, depth, col, pix, xmask, pmask;
	ulong chan;
	Rectangle r;

	if(memimage != nil){
		r = memimage->r;
		depth = memimage->depth;
		chan = memimage->chan;
	}else{
		r = image->r;
		depth = image->depth;
		chan = image->chan;
	}

	/* 
	 * Read image data into memory
	 * potentially one extra byte on each end of each scan line
	 */
	ndata = Dy(r)*(2+Dx(r)*depth/8);
	data = malloc(ndata);
	if(data == nil)
		return "WritePPM: malloc failed";
	if(memimage != nil)
		ndata = unloadmemimage(memimage, r, data, ndata);
	else
		ndata = unloadimage(image, r, data, ndata);
	if(ndata < 0){
		err = malloc(ERRMAX);
		if(err == nil)
			return "WritePPM: malloc failed";
		snprint(err, ERRMAX, "WriteGIF: %r");
		free(data);
		return err;
	}

	/* Encode and emit the data */
	col = 0;
	switch(chan){
	case GREY1:
	case GREY2:
	case GREY4:
		pmask = (1<<depth)-1;
		xmask = 7>>drawlog2[depth];
		for(y=r.min.y; y<r.max.y; y++){
			i = (y-r.min.y)*bytesperline(r, depth);
			for(x=r.min.x; x<r.max.x; x++){
				pix = (data[i]>>depth*((xmask-x)&xmask))&pmask;
				if(((x+1)&xmask) == 0)
					i++;
				col += Bprint(fd, "%d ", pix);
				if(col >= MAXLINE-(2+1)){
					Bprint(fd, "\n");
					col = 0;
				}else
					col += Bprint(fd, " ");
			}
		}
		break;
	case	GREY8:
		for(i=0; i<ndata; i++){
			col += Bprint(fd, "%d ", data[i]);
			if(col >= MAXLINE-(4+1)){
				Bprint(fd, "\n");
				col = 0;
			}else
				col += Bprint(fd, " ");
		}
		break;
	case RGB24:
		for(i=0; i<ndata; i+=3){
			col += Bprint(fd, "%d %d %d", data[i+2], data[i+1], data[i]);
			if(col >= MAXLINE-(4+4+4+1)){
				Bprint(fd, "\n");
				col = 0;
			}else
				col += Bprint(fd, " ");
		}
		break;
	default:
		return "WritePPM: can't handle channel type";
	}

	return nil;
}

static
char*
writeppm0(Biobuf *fd, Image *image, Memimage *memimage, Rectangle r, int chan, char *comment)
{
	char *err;

	switch(chan){
	case GREY1:
		Bprint(fd, "P1\n");
		break;
	case GREY2:
	case GREY4:
	case	GREY8:
		Bprint(fd, "P2\n");
		break;
	case RGB24:
		Bprint(fd, "P3\n");
		break;
	default:
		return "WritePPM: can't handle channel type";
	}

	if(comment!=nil && comment[0]!='\0'){
		Bprint(fd, "# %s", comment);
		if(comment[strlen(comment)-1] != '\n')
			Bprint(fd, "\n");
	}
	Bprint(fd, "%d %d\n", Dx(r), Dy(r));

	/* maximum pixel value */
	switch(chan){
	case GREY2:
		Bprint(fd, "%d\n", 3);
		break;
	case GREY4:
		Bprint(fd, "%d\n", 15);
		break;
	case	GREY8:
	case RGB24:
		Bprint(fd, "%d\n", 255);
		break;
	}

	err = writedata(fd, image, memimage);

	Bprint(fd, "\n");
	Bflush(fd);
	return err;
}

char*
writeppm(Biobuf *fd, Image *image, char *comment)
{
	return writeppm0(fd, image, nil, image->r, image->chan, comment);
}

char*
memwriteppm(Biobuf *fd, Memimage *memimage, char *comment)
{
	return writeppm0(fd, nil, memimage, memimage->r, memimage->chan, comment);
}
