/*
 * Copyright © 2010 Kristian Høgsberg
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "config.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <cairo.h>

#include <wayland-client.h>
#include "window.h"

struct smoke {
	struct display *display;
	struct window *window;
	struct widget *widget;
	int width, height;
	int current;
	struct { float *d, *u, *v; } b[2];
};

static void diffuse(struct smoke *smoke, uint32_t time,
		    float *source, float *dest)
{
	float *s, *d;
	int x, y, k, stride;
	float t, a = 0.0002;

	stride = smoke->width;

	for (k = 0; k < 5; k++) {
		for (y = 1; y < smoke->height - 1; y++) {
			s = source + y * stride;
			d = dest + y * stride;
			for (x = 1; x < smoke->width - 1; x++) {
				t = d[x - 1] + d[x + 1] +
					d[x - stride] + d[x + stride];
				d[x] = (s[x] + a * t) / (1 + 4 * a) * 0.995;
			}
		}
	}
}

static void advect(struct smoke *smoke, uint32_t time,
		   float *uu, float *vv, float *source, float *dest)
{
	float *s, *d;
	float *u, *v;
	int x, y, stride;
	int i, j;
	float px, py, fx, fy;

	stride = smoke->width;

	for (y = 1; y < smoke->height - 1; y++) {
		d = dest + y * stride;
		u = uu + y * stride;
		v = vv + y * stride;

		for (x = 1; x < smoke->width - 1; x++) {
			px = x - u[x];
			py = y - v[x];
			if (px < 0.5)
				px = 0.5;
			if (py < 0.5)
				py = 0.5;
			if (px > smoke->width - 1.5)
				px = smoke->width - 1.5;
			if (py > smoke->height - 1.5)
				py = smoke->height - 1.5;
			i = (int) px;
			j = (int) py;
			fx = px - i;
			fy = py - j;
			s = source + j * stride + i;
			d[x] = (s[0] * (1 - fx) + s[1] * fx) * (1 - fy) +
				(s[stride] * (1 - fx) + s[stride + 1] * fx) * fy;
		}
	}
}

static void project(struct smoke *smoke, uint32_t time,
		    float *u, float *v, float *p, float *div)
{
	int x, y, k, l, s;
	float h;

	h = 1.0 / smoke->width;
	s = smoke->width;
	memset(p, 0, smoke->height * smoke->width);
	for (y = 1; y < smoke->height - 1; y++) {
		l = y * s;
		for (x = 1; x < smoke->width - 1; x++) {
			div[l + x] = -0.5 * h * (u[l + x + 1] - u[l + x - 1] +
						 v[l + x + s] - v[l + x - s]);
			p[l + x] = 0;
		}
	}

	for (k = 0; k < 5; k++) {
		for (y = 1; y < smoke->height - 1; y++) {
			l = y * s;
			for (x = 1; x < smoke->width - 1; x++) {
				p[l + x] = (div[l + x] +
					    p[l + x - 1] +
					    p[l + x + 1] +
					    p[l + x - s] +
					    p[l + x + s]) / 4;
			}
		}
	}

	for (y = 1; y < smoke->height - 1; y++) {
		l = y * s;
		for (x = 1; x < smoke->width - 1; x++) {
			u[l + x] -= 0.5 * (p[l + x + 1] - p[l + x - 1]) / h;
			v[l + x] -= 0.5 * (p[l + x + s] - p[l + x - s]) / h;
		}
	}
}

static void render(struct smoke *smoke, cairo_surface_t *surface)
{
	unsigned char *dest;
	int x, y, width, height, stride;
	float *s;
	uint32_t *d, c, a;

	dest = cairo_image_surface_get_data(surface);
	width = cairo_image_surface_get_width(surface);
	height = cairo_image_surface_get_height(surface);
	stride = cairo_image_surface_get_stride(surface);

	for (y = 1; y < height - 1; y++) {
		s = smoke->b[smoke->current].d + y * smoke->height;
		d = (uint32_t *) (dest + y * stride);
		for (x = 1; x < width - 1; x++) {
			c = (int) (s[x] * 800);
			if (c > 255)
				c = 255;
			a = c;
			if (a < 0x33)
				a = 0x33;
			d[x] = (a << 24) | (c << 16) | (c << 8) | c;
		}
	}
}

static void
redraw_handler(struct widget *widget, void *data)
{
	struct smoke *smoke = data;
	uint32_t time = widget_get_last_time(smoke->widget);
	cairo_surface_t *surface;

	diffuse(smoke, time / 30, smoke->b[0].u, smoke->b[1].u);
	diffuse(smoke, time / 30, smoke->b[0].v, smoke->b[1].v);
	project(smoke, time / 30,
		smoke->b[1].u, smoke->b[1].v,
		smoke->b[0].u, smoke->b[0].v);
	advect(smoke, time / 30,
	       smoke->b[1].u, smoke->b[1].v,
	       smoke->b[1].u, smoke->b[0].u);
	advect(smoke, time / 30,
	       smoke->b[1].u, smoke->b[1].v,
	       smoke->b[1].v, smoke->b[0].v);
	project(smoke, time / 30,
		smoke->b[0].u, smoke->b[0].v,
		smoke->b[1].u, smoke->b[1].v);

	diffuse(smoke, time / 30, smoke->b[0].d, smoke->b[1].d);
	advect(smoke, time / 30,
	       smoke->b[0].u, smoke->b[0].v,
	       smoke->b[1].d, smoke->b[0].d);

	surface = window_get_surface(smoke->window);

	render(smoke, surface);

	cairo_surface_destroy(surface);

	widget_schedule_redraw(smoke->widget);
}

static void
smoke_motion_handler(struct smoke *smoke, float x, float y)
{
	int i, i0, i1, j, j0, j1, k, d = 5;

	if (x - d < 1)
		i0 = 1;
	else
		i0 = x - d;
	if (i0 + 2 * d > smoke->width - 1)
		i1 = smoke->width - 1;
	else
		i1 = i0 + 2 * d;

	if (y - d < 1)
		j0 = 1;
	else
		j0 = y - d;
	if (j0 + 2 * d > smoke->height - 1)
		j1 = smoke->height - 1;
	else
		j1 = j0 + 2 * d;

	for (i = i0; i < i1; i++)
		for (j = j0; j < j1; j++) {
			k = j * smoke->width + i;
			smoke->b[0].u[k] += 256 - (random() & 512);
			smoke->b[0].v[k] += 256 - (random() & 512);
			smoke->b[0].d[k] += 1;
		}
}

static int
mouse_motion_handler(struct widget *widget, struct input *input,
		     uint32_t time, float x, float y, void *data)
{
	smoke_motion_handler(data, x, y);

	return CURSOR_HAND1;
}

static void
touch_motion_handler(struct widget *widget, struct input *input,
		     uint32_t time, int32_t id, float x, float y, void *data)
{
	smoke_motion_handler(data, x, y);
}

static void
resize_handler(struct widget *widget,
	       int32_t width, int32_t height, void *data)
{
	struct smoke *smoke = data;

	/* Don't resize me */
	widget_set_size(smoke->widget, smoke->width, smoke->height);
}

int main(int argc, char *argv[])
{
	struct timespec ts;
	struct smoke smoke;
	struct display *d;
	int size;

	d = display_create(&argc, argv);
	if (d == NULL) {
		fprintf(stderr, "failed to create display: %m\n");
		return -1;
	}

	smoke.width = 200;
	smoke.height = 200;
	smoke.display = d;
	smoke.window = window_create(d);
	smoke.widget = window_add_widget(smoke.window, &smoke);
	window_set_title(smoke.window, "smoke");

	window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM);
	clock_gettime(CLOCK_MONOTONIC, &ts);
	srandom(ts.tv_nsec);

	smoke.current = 0;
	size = smoke.height * smoke.width;
	smoke.b[0].d = calloc(size, sizeof(float));
	smoke.b[0].u = calloc(size, sizeof(float));
	smoke.b[0].v = calloc(size, sizeof(float));
	smoke.b[1].d = calloc(size, sizeof(float));
	smoke.b[1].u = calloc(size, sizeof(float));
	smoke.b[1].v = calloc(size, sizeof(float));

	widget_set_motion_handler(smoke.widget, mouse_motion_handler);
	widget_set_touch_motion_handler(smoke.widget, touch_motion_handler);
	widget_set_resize_handler(smoke.widget, resize_handler);
	widget_set_redraw_handler(smoke.widget, redraw_handler);

	window_set_user_data(smoke.window, &smoke);

	widget_schedule_resize(smoke.widget, smoke.width, smoke.height);

	display_run(d);

	widget_destroy(smoke.widget);
	window_destroy(smoke.window);
	display_destroy(d);

	return 0;
}
