#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <keyboard.h>
#include <mouse.h>

enum
{
	STACK = 8192
};

int nbit, npix;
Image *pixel;
Rectangle crect[256];
Image *color[256];
char *fmt;
int ramp;

Mousectl *mousectl;
Keyboardctl *keyboardctl;

void keyboardthread(void*);
void mousethread(void*);
void resizethread(void*);

ulong
grey(int i)
{
	if(i < 0)
		return grey(0);
	if(i > 255)
		return grey(255);
	return (i<<16)+(i<<8)+i;
}

int
dither[16] =  {
	0, 8, 2, 10,
	12, 4, 14, 6,
	3, 11, 1, 9,
	15, 7, 13, 5
};

extern int chattydrawclient;

void
threadmain(int argc, char *argv[])
{
	int i, j, k, l;
	Image *dark;

	ramp = 0;

	fmt = "index %3d r %3lud g %3lud b %3lud 0x%.8luX        ";
	ARGBEGIN{
	default:
		goto Usage;
	case 'D':
		chattydrawclient = 1;
		break;
	case 'x':
		fmt = "index %2luX r %3luX g %3luX b %3luX 0x%.8luX       ";
		break;
	case 'r':
		ramp = 1;
		break;
	}ARGEND

	if(argc){
	Usage:
		fprint(2, "Usage: %s [-rx]\n", argv0);
		threadexitsall("usage");
	}

	if(initdraw(0, nil, "colors") < 0)
		sysfatal("initdraw failed: %r");

	mousectl = initmouse(nil, display->image);
	if(mousectl == nil)
		sysfatal("initmouse: %r");

	keyboardctl = initkeyboard(nil);
	if(keyboardctl == nil)
		sysfatal("initkeyboard: %r");

	for(i=0; i<256; i++){
		if(ramp){
			if(screen->chan == CMAP8){
				/* dither the fine grey */
				j = i-(i%17);
				dark = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (grey(j)<<8)+0xFF);
				color[i] = allocimage(display, Rect(0,0,4,4), screen->chan, 1, (grey(j+17)<<8)+0xFF);
				for(j=0; j<16; j++){
					k = j%4;
					l = j/4;
					if(dither[j] > (i%17))
						draw(color[i], Rect(k, l, k+1, l+1), dark, nil, ZP);
				}
				freeimage(dark);
			}else
				color[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (grey(i)<<8)+0xFF);
		}else
			color[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (cmap2rgb(i)<<8)+0xFF);
		if(color[i] == nil)
			sysfatal("can't allocate image: %r");
	}

	threadcreate(mousethread, nil, STACK);
	threadcreate(keyboardthread, nil, STACK);
	threadcreate(resizethread, nil, STACK);
}

void
keyboardthread(void *v)
{
	Rune r;

	USED(v);

	while(recv(keyboardctl->c, &r) >= 0)
		;
}

char *buttons[] =
{
	"exit",
	0
};

Menu menu =
{
	buttons
};

void
mousethread(void *v)
{
	Point p;
	Mouse m;
	int i, n, prev;
	char buf[100];
	ulong rgb;

	prev = -1;
	while(readmouse(mousectl) >= 0){
		m = mousectl->m;
		switch(m.buttons){
		case 1:
			while(m.buttons){
				if(screen->depth > 8)
					n = 256;
				else
					n = 1<<screen->depth;
				for(i=0; i!=n; i++)
					if(i!=prev && ptinrect(m.xy, crect[i])){
						if(ramp)
							rgb = grey(i);
						else
							rgb = cmap2rgb(i);
						sprint(buf, fmt,
							i,
							(rgb>>16)&0xFF,
							(rgb>>8)&0xFF,
							rgb&0xFF,
							(rgb<<8) | 0xFF);
						p = addpt(screen->r.min, Pt(2,2));
						draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->white, nil, p);
						string(screen, p, display->black, ZP, font, buf);
						prev=i;
						break;
					}
				readmouse(mousectl);
				m = mousectl->m;
			}
			break;

		case 4:
			switch(menuhit(3, mousectl, &menu, nil)){
			case 0:
				threadexitsall(0);
			}
		}
	}
}

void
eresized(int new)
{
	int x, y, i, n, nx, ny;
	Rectangle r, b;

	if(new && getwindow(display, Refnone) < 0){
		fprint(2, "colors: can't reattach to window: %r\n");
		threadexitsall("resized");
	}
	if(screen->depth > 8){
		n = 256;
		nx = 16;
	}else{
		n = 1<<screen->depth;
		nx = 1<<(screen->depth/2);
	}

	ny = n/nx;
	draw(screen, screen->r, display->white, nil, ZP);
	r = insetrect(screen->r, 5);
	r.min.y+=20;
	b.max.y=r.min.y;
	for(i=n-1, y=0; y!=ny; y++){
		b.min.y=b.max.y;
		b.max.y=r.min.y+(r.max.y-r.min.y)*(y+1)/ny;
		b.max.x=r.min.x;
		for(x=0; x!=nx; x++, --i){
			b.min.x=b.max.x;
			b.max.x=r.min.x+(r.max.x-r.min.x)*(x+1)/nx;
			crect[i]=insetrect(b, 1);
			draw(screen, crect[i], color[i], nil, ZP);
		}
	}
	flushimage(display, 1);
}

void
resizethread(void *v)
{
	ulong x;

	USED(v);

	eresized(0);
	while(recv(mousectl->resizec, &x) >= 0)
		eresized(1);
}

