/* quirc -- QR-code recognition library
 * Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <string.h>
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include "quirc_internal.h"
#include "dbgutil.h"

static void dump_info(struct quirc *q)
{
	int count = quirc_count(q);
	int i;

	printf("%d QR-codes found:\n\n", count);
	for (i = 0; i < count; i++) {
		struct quirc_code code;
		struct quirc_data data;
		quirc_decode_error_t err;

		quirc_extract(q, i, &code);
		err = quirc_decode(&code, &data);

		dump_cells(&code);
		printf("\n");

		if (err) {
			printf("  Decoding FAILED: %s\n", quirc_strerror(err));
		} else {
			printf("  Decoding successful:\n");
			dump_data(&data);
		}

		printf("\n");
	}
}

static void draw_frame(SDL_Surface *screen, struct quirc *q)
{
	uint8_t *pix;
	uint8_t *raw = q->image;
	int x, y;

	SDL_LockSurface(screen);
	pix = screen->pixels;
	for (y = 0; y < q->h; y++) {
		uint32_t *row = (uint32_t *)pix;

		for (x = 0; x < q->w; x++) {
			uint8_t v = *(raw++);
			uint32_t color = (v << 16) | (v << 8) | v;
			struct quirc_region *reg = &q->regions[v];

			switch (v) {
			case QUIRC_PIXEL_WHITE:
				color = 0x00ffffff;
				break;

			case QUIRC_PIXEL_BLACK:
				color = 0x00000000;
				break;

			default:
				if (reg->capstone >= 0)
					color = 0x00008000;
				else
					color = 0x00808080;
				break;
			}

			*(row++) = color;
		}

		pix += screen->pitch;
	}
	SDL_UnlockSurface(screen);
}

static void draw_blob(SDL_Surface *screen, int x, int y)
{
	int i, j;

	for (i = -2; i <= 2; i++)
		for (j = -2; j <= 2; j++)
			pixelColor(screen, x + i, y + j, 0x0000ffff);
}

static void draw_mark(SDL_Surface *screen, int x, int y)
{
	pixelColor(screen, x, y, 0xff0000ff);
	pixelColor(screen, x + 1, y, 0xff0000ff);
	pixelColor(screen, x - 1, y, 0xff0000ff);
	pixelColor(screen, x, y + 1, 0xff0000ff);
	pixelColor(screen, x, y - 1, 0xff0000ff);
}

static void draw_capstone(SDL_Surface *screen, struct quirc *q, int index)
{
	struct quirc_capstone *cap = &q->capstones[index];
	int j;
	char buf[8];

	for (j = 0; j < 4; j++) {
		struct quirc_point *p0 = &cap->corners[j];
		struct quirc_point *p1 = &cap->corners[(j + 1) % 4];

		lineColor(screen, p0->x, p0->y, p1->x, p1->y,
			  0x800080ff);
	}

	draw_blob(screen, cap->corners[0].x, cap->corners[0].y);

	if (cap->qr_grid < 0) {
		snprintf(buf, sizeof(buf), "?%d", index);
		stringColor(screen, cap->center.x, cap->center.y, buf,
			    0x000000ff);
	}
}

static void perspective_map(const double *c,
			    double u, double v, struct quirc_point *ret)
{
	double den = c[6]*u + c[7]*v + 1.0;
	double x = (c[0]*u + c[1]*v + c[2]) / den;
	double y = (c[3]*u + c[4]*v + c[5]) / den;

	ret->x = rint(x);
	ret->y = rint(y);
}

static void draw_grid(SDL_Surface *screen, struct quirc *q, int index)
{
	struct quirc_grid *qr = &q->grids[index];
	int x, y;
	int i;

	for (i = 0; i < 3; i++) {
		struct quirc_capstone *cap = &q->capstones[qr->caps[i]];
		char buf[8];

		snprintf(buf, sizeof(buf), "%d.%c", index, "ABC"[i]);
		stringColor(screen, cap->center.x, cap->center.y, buf,
			    0x000000ff);
	}

	lineColor(screen, qr->tpep[0].x, qr->tpep[0].y,
		  qr->tpep[1].x, qr->tpep[1].y, 0xff00ffff);
	lineColor(screen, qr->tpep[1].x, qr->tpep[1].y,
		  qr->tpep[2].x, qr->tpep[2].y, 0xff00ffff);

	if (qr->align_region >= 0)
		draw_blob(screen, qr->align.x, qr->align.y);

	for (y = 0; y < qr->grid_size; y++) {
		for (x = 0; x < qr->grid_size; x++) {
			double u = x + 0.5;
			double v = y + 0.5;
			struct quirc_point p;

			perspective_map(qr->c, u, v, &p);
			draw_mark(screen, p.x, p.y);
		}
	}
}

static int sdl_examine(struct quirc *q)
{
	SDL_Surface *screen;
	SDL_Event ev;

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		fprintf(stderr, "couldn't init SDL: %s\n", SDL_GetError());
		return -1;
	}

	screen = SDL_SetVideoMode(q->w, q->h, 32, SDL_SWSURFACE);
	if (!screen) {
		fprintf(stderr, "couldn't init video mode: %s\n",
			SDL_GetError());
		return -1;
	}

	while (SDL_WaitEvent(&ev) >= 0) {
		int i;

		if (ev.type == SDL_QUIT)
			break;

		if (ev.type == SDL_KEYDOWN &&
		    ev.key.keysym.sym == 'q')
			break;

		draw_frame(screen, q);
		for (i = 0; i < q->num_capstones; i++)
			draw_capstone(screen, q, i);
		for (i = 0; i < q->num_grids; i++)
			draw_grid(screen, q, i);
		SDL_Flip(screen);
	}

	SDL_Quit();
	return 0;
}

int main(int argc, char **argv)
{
	struct quirc *q;

	printf("quirc inspection program\n");
	printf("Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>\n");
	printf("Library version: %s\n", quirc_version());
	printf("\n");

	if (argc < 2) {
		fprintf(stderr, "Usage: %s <testfile.jpg|testfile.png>\n", argv[0]);
		return -1;
	}

	q = quirc_new();
	if (!q) {
		perror("can't create quirc object");
		return -1;
	}

	int status = -1;
	if (check_if_png(argv[1])) {
		status = load_png(q, argv[1]);
	} else {
		status = load_jpeg(q, argv[1]);
	}
	if (status < 0) {
		quirc_destroy(q);
		return -1;
	}

	quirc_end(q);
	dump_info(q);

	if (sdl_examine(q) < 0) {
		quirc_destroy(q);
		return -1;
	}

	quirc_destroy(q);
	return 0;
}
