#include "fdf.h"

t_trnsf	*transfor_mat_init()
{
	t_trnsf	*trnsf;

	trnsf = NULL;
	if ((trnsf = malloc(sizeof(t_trnsf))))
	{
		trnsf->tr = mat4_init();
		trnsf->xr = mat4_init();
		trnsf->yr = mat4_init();
		trnsf->zr = mat4_init();
		trnsf->fin = mat4_init();
	}
	return (trnsf);
}

void	transform(t_mat4 *mat, t_map *map)
{
	t_list *vec_list;
	int 	i;
	int 	j;

	vec_list = map->lst_map;
	i = 0;
	while (i <= map->y_max)
	{
		j = 0;
		while (j <= map->x_max)
		{
			vec_mat_mult(mat, vec_list->content, &map->arr_pnt[i][j]);
			vec_list = vec_list->next;
			j++;
		}
		i++;
	}
}

t_mat4 *viewport_mat_init(int x, int y)
{
	t_mat4 *m;

	if ((m = malloc(sizeof(t_mat4))))
	{
		m->mx[0][0] = (double)x / 2.0f;
		m->mx[0][1] = 0;
		m->mx[0][2] = 0;
		m->mx[0][3] = 0;
		m->mx[1][0] = 0;
		m->mx[1][1] = (double)y / 2.0f;
		m->mx[1][2] = 0;
		m->mx[1][3] = 0;
		m->mx[2][0] = 0;
		m->mx[2][1] = 0;
		m->mx[2][2] = 1;
		m->mx[2][3] = 0;
		m->mx[3][0] = ((double)x - 1) / 2.0f;
		m->mx[3][1] = ((double)y - 1) / 2.0f;
		m->mx[3][2] = 0;
		m->mx[3][3] = 1;
	}
	return (m);
}

t_mat4	*orth_mat_init(int l, int r, int b, int t, int n, int f)
{
	t_mat4 *orth;

	if ((orth = malloc(sizeof(t_mat4))))
	{
		orth->mx[0][0] = 2.0f / ((double)r - (double)l);
		orth->mx[0][1] = 0;
		orth->mx[0][2] = 0;
		orth->mx[0][3] = 0;
		orth->mx[1][0] = 0;
		orth->mx[1][1] = 2.0f / ((double)t - (double)b);
		orth->mx[1][2] = 0;
		orth->mx[1][3] = 0;
		orth->mx[2][0] = 0;
		orth->mx[2][1] = 0;
		orth->mx[2][2] = 2.0f / ((double)n - (double)f);
		orth->mx[2][3] = 0;
		orth->mx[3][0] = - (((double)r + (double)l) / ((double)r - (double)l));
		orth->mx[3][1] = - (((double)t + (double)b) / ((double)t - (double)b));
		orth->mx[3][2] = - (((double)n + (double)f) / ((double)n - (double)f));
		orth->mx[3][3] = 1;
	}
	return (orth);
}

void	draw(t_FDF *FDF)
{
	int 	i;
	int 	j;
	t_map	*map;

	map = FDF->map;
	i = 0;
	while (i <= map->y_max)
	{
		j = 0;
		while (j <= map->x_max)
		{
			if (i == map->y_max && j < map->x_max)
				line(map->arr_pnt[i][j], map->arr_pnt[i][j + 1], FDF);
			else if (i < map->y_max && j == map->x_max)
				line(map->arr_pnt[i][j], map->arr_pnt[i + 1][j], FDF);
			else if (i < map->y_max && j < map->x_max)
			{
				line(map->arr_pnt[i][j], map->arr_pnt[i + 1][j], FDF);
				line(map->arr_pnt[i][j], map->arr_pnt[i][j + 1], FDF);
			}
			j++;
		}
		i++;
	}
	mlx_put_image_to_window(FDF->mw->mlx, FDF->mw->win, FDF->image, 0, 0);
}

void	center(t_map *map)
{
	t_list	*l;
	double 	d_x;
	double	d_y;
	double	d_z;


	d_x = map->x_max / 2.0f;
	d_y = map->y_max / 2.0f;
	d_z = map->z_max / 2.0f;
	l = map->lst_map;
	while (l)
	{
		((t_vec *)(l->content))->x = ((t_vec *)(l->content))->x - d_x;
		((t_vec *)(l->content))->y = ((t_vec *)(l->content))->y - d_y;
		((t_vec *)(l->content))->z = ((t_vec *)(l->content))->z - d_z;
		l = l->next;
	}
}

void	render(t_FDF *FDF)
{
	t_mat4	*vp;
	t_mat4	*orth;
	t_mat4	*final;
	t_mat4	*rot_z;
	t_mat4	*rot_y;
	t_mat4	*rot_x;
	t_mat4	*translate;
	t_mat4	*scale;

	rot_x = mat4_init();
	rot_y = mat4_init();
	rot_z = mat4_init();
	translate = mat4_init();
	scale = mat4_init();
	final = mat4_init();
	vp = viewport_mat_init(FDF->w_width, FDF->w_height);
	orth = orth_mat_init(
			0,
			FDF->map->x_max + 2,
			0,
			FDF->map->x_max + 2,
			0,
			FDF->map->z_max + 2);
	mat4_x_rot(rot_x, 30);
	mat4_z_rot(rot_z, -45);
	mat4_y_rot(rot_y, -20);
	mat4_scale(scale, 0.9, 0.9, 0.1);
	mat4_translate(
			translate,
			(((double)FDF->map->x_max) / 2.0f),
			(((double)FDF->map->x_max) / 2.0f),
			(((double)FDF->map->z_max) / 2.0f));
	final = mat4_mult(vp, orth);
	final = mat4_mult(translate, final);
	final = mat4_mult(rot_z ,final);
	final = mat4_mult(rot_x, final);
	final = mat4_mult(rot_y ,final);
	final = mat4_mult(scale, final);

	center(FDF->map);
	transform(final, FDF->map);
	draw(FDF);
}

