
#include <X11/Xlib.h>
#include "wraster.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef BENCH
#include <sys/time.h>
#include <time.h>
#endif

Display *dpy;
Window win;
RContext *ctx;
RImage *imgh, *imgv, *imgd;
Pixmap pix;
char *ProgName;

void print_help()
{
	printf("usage: %s [-options] color1 [color2 ...]\n", ProgName);
	puts("options:");
	puts(" -m 		match  colors");
	puts(" -d		dither colors (default)");
	puts(" -c <cpc>	colors per channel to use");
	puts(" -v <vis-id>	visual id to use");
}

#ifdef BENCH
#include "bench.h"
#endif
int main(int argc, char **argv)
{
	RContextAttributes attr;
	RColor **colors = NULL;
	int i, rmode = RDitheredRendering, ncolors = 0, cpc = 4;
	char **color_name;
	XColor color;
	XSetWindowAttributes val;
	int visualID = -1;
#ifdef BENCH
	double t1, t2, total, t, rt;
	struct timeval timev;
#endif

	ProgName = strrchr(argv[0], '/');
	if (!ProgName)
		ProgName = argv[0];
	else
		ProgName++;

	color_name = (char **)malloc(sizeof(char *) * argc);
	if (color_name == NULL) {
		fprintf(stderr, "Cannot allocate memory!\n");
		exit(1);
	}

	if (argc > 1) {
		for (i = 1; i < argc; i++) {
			if (strcmp(argv[i], "-m") == 0) {
				rmode = RBestMatchRendering;
			} else if (strcmp(argv[i], "-d") == 0) {
				rmode = RDitheredRendering;
			} else if (strcmp(argv[i], "-c") == 0) {
				i++;
				if (i >= argc) {
					fprintf(stderr, "too few arguments for %s\n", argv[i - 1]);
					exit(0);
				}
				if (sscanf(argv[i], "%i", &cpc) != 1) {
					fprintf(stderr, "bad value for colors per channel: \"%s\"\n", argv[i]);
					exit(0);
				}
			} else if (strcmp(argv[i], "-v") == 0) {
				i++;
				if (i >= argc) {
					fprintf(stderr, "too few arguments for %s\n", argv[i - 1]);
					exit(0);
				}
				if (sscanf(argv[i], "%i", &visualID) != 1) {
					fprintf(stderr, "bad value for visual ID: \"%s\"\n", argv[i]);
					exit(0);
				}
			} else if (argv[i][0] != '-') {
				color_name[ncolors++] = argv[i];
			} else {
				print_help();
				exit(1);
			}
		}
	}

	if (ncolors == 0) {
		print_help();
		exit(1);
	}

	dpy = XOpenDisplay("");
	if (!dpy) {
		puts("cant open display");
		exit(1);
	}
	attr.flags = RC_RenderMode | RC_ColorsPerChannel;

	attr.render_mode = rmode;
	attr.colors_per_channel = cpc;

	if (visualID >= 0) {
		attr.flags |= RC_VisualID;
		attr.visualid = visualID;
	}

	ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);

	if (!ctx) {
		printf("could not initialize graphics library context: %s\n", RMessageForError(RErrorCode));
		exit(1);
	}

	colors = malloc(sizeof(RColor *) * (ncolors + 1));
	for (i = 0; i < ncolors; i++) {
		if (!XParseColor(dpy, ctx->cmap, color_name[i], &color)) {
			printf("could not parse color \"%s\"\n", color_name[i]);
			exit(1);
		} else {
			colors[i] = malloc(sizeof(RColor));
			colors[i]->red = color.red >> 8;
			colors[i]->green = color.green >> 8;
			colors[i]->blue = color.blue >> 8;
			printf("0x%02x%02x%02x\n", colors[i]->red, colors[i]->green, colors[i]->blue);
		}
	}
	colors[i] = NULL;

	val.background_pixel = ctx->black;
	val.colormap = ctx->cmap;
	val.backing_store = Always;
#ifdef BENCH
	win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 250, 250,
			    0, ctx->depth, InputOutput, ctx->visual,
			    CWColormap | CWBackPixel | CWBackingStore, &val);
#else
	win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 750, 250,
			    0, ctx->depth, InputOutput, ctx->visual,
			    CWColormap | CWBackPixel | CWBackingStore, &val);
#endif
	XMapRaised(dpy, win);
	XFlush(dpy);

#ifdef BENCH
	rt = 0;
	gettimeofday(&timev, NULL);
	t = (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
	for (i = 0; i < 9; i++) {
		if (i > 0)
			printf("\nrepeating...\n\n");
		gettimeofday(&timev, NULL);
		t1 = (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
		if (i % 3 == 0)
			imgh = RRenderMultiGradient(550, 550, colors, RGRD_HORIZONTAL);
		else if (i % 3 == 1)
			imgh = RRenderMultiGradient(550, 550, colors, RGRD_VERTICAL);
		else
			imgh = RRenderMultiGradient(550, 550, colors, RGRD_DIAGONAL);

		gettimeofday(&timev, NULL);
		t2 = (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
		total = t2 - t1;
		printf("gradient rendered in %f sec\n", total);

		RConvertImage(ctx, imgh, &pix);
		gettimeofday(&timev, NULL);
		t1 = (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
		total = t1 - t2;
		rt += total;
		printf("image converted in %f sec\n", total);

		XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0);

		XFlush(dpy);
	}
	t1 = (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
	printf("------------------------------------------\n");
	printf("%i images processed in %f sec\n", i, t1 - t);
	printf("average time per convertion %f sec\n", rt / i);
	printf("------------------------------------------\n");
#else
	imgh = RRenderMultiGradient(250, 250, colors, RGRD_HORIZONTAL);
	imgv = RRenderMultiGradient(250, 250, colors, RGRD_VERTICAL);
	imgd = RRenderMultiGradient(250, 250, colors, RGRD_DIAGONAL);
	RConvertImage(ctx, imgh, &pix);
	XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0);

	RConvertImage(ctx, imgv, &pix);
	XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 250, 0);

	RConvertImage(ctx, imgd, &pix);
	XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 500, 0);

	XFlush(dpy);
#endif

	getchar();
	return 0;
}
