#include "fdf.h"
#include <stdio.h>

void	draw_image(t_fdf *fdf)
{
	int	i;
	int	j;

	fdf->rad_x = fdf->rot_x * M_PI / 180;
	fdf->rad_y = fdf->rot_y * M_PI / 180;
	i = -1;
	while (++i < fdf->img_size_y * fdf->img_sizel)
		*(unsigned int *)(fdf->img_addr + i) = 0;
	j = -1;
	while (++j < fdf->map_height)
	{
		i = -1;
		while (++i < fdf->map_width)
			draw_grid(fdf, i, j);
	}
	mlx_put_image_to_window(fdf->mlx_ptr, fdf->win_ptr, fdf->img_ptr, 0, 0);
	position_state(fdf);
}

void	draw_grid(t_fdf *fdf, int i, int j)
{
	int	*point_start;
	int	*point_end;

	point_start = new_coordinates(fdf, i, j);
	point_end = NULL;
	if (i + 1 < fdf->map_width)
		point_end = new_coordinates(fdf, i + 1, j);
	draw_lines(fdf, point_start, point_end);
	free(point_end);
	point_end = NULL;
	if (j + 1 < fdf->map_height)
		point_end = new_coordinates(fdf, i, j + 1);
	draw_lines(fdf, point_start, point_end);
	free(point_start);
	free(point_end);
}

void	draw_lines(t_fdf *fdf, int *start, int *end)
{
	int	dx;
	int	dy;
	int	i;
	int	j;
	int	percent;

	if (end)
	{
		dx = end[0] - start[0];
		dy = end[1] - start[1];
		i = 0;
		j = 0;
		while (ft_abs(i) <= ft_abs(dx) && ft_abs(j) <= ft_abs(dy))
		{
			if (!is_outise_screen(fdf, start[0] + i, start[1] + j))
			{
				percent = color_percent(fdf, start, end, ft_abs(i) + ft_abs(j), ft_abs(dx) + ft_abs(dy));
				draw_color_pixel(fdf, start[0] + i, start[1] + j, percent);
			}
			if (!ft_abs(dx) || ft_abs(j) < ft_abs(i * dy / dx))
				j += ft_sign(dy);
			else
				i += ft_sign(dx);
		}
	}
}

// return the position of the point p
// in percentage of the total height of the map :
//   z_min---start---point---end----z_max
//   0%--------s%-----p-------e%-----100%
//   line:       -------------
//           ex. . . . . . ---e
//                      ---   .
//           px. . . -p-      .
//                ---.        .
//             s--   .        .
//                   py       ey
// return value is 0 <= X <= 100
// - z_total       : z_max - z_min
// - start         : start
// - line          : end - start
// - p_numerator   : px + py
// - p_denominator : ex + ey
int	color_percent(t_fdf *fdf, int *p_start, int *p_end, int p_numerator, int p_denominator)
{
	int z_total;
	int start;
	int line;
	int percent;

	z_total = fdf->z_amplitude;
	line = ft_abs(p_end[3] - p_start[3]);
	line *= 100;
	if (p_start[3] < p_end[3])
	{
		start = p_start[3] - fdf->min_z;
		start *= 100;
	}
	else
	{
		start = p_end[3] - fdf->min_z;
		start *= 100;
		p_numerator = p_denominator - p_numerator;
	}
	if (p_denominator != 0)
		percent = (start + line * p_numerator / p_denominator);
	if (z_total != 0)
		percent /= z_total;
	else
		percent = 0;
	return (percent);
}

void	draw_color_pixel(t_fdf *fdf, int new_x, int new_y, int percent)
{
	int	color_r;
	int	color_g;
	int	color_b;
	int	color;

	color_r = get_primary_color('r', percent);
	color_g = get_primary_color('g', percent);
	color_b = get_primary_color('b', percent);
	color = (color_r << 16) + (color_g << 8) + color_b;
	draw_pixel(fdf, new_x, new_y, color);
}

int	get_primary_color(char primar, int percent)
{
	int	start_color;
	int	end_color;
	int	new_primary_color;
	int	offset;

	if ((primar == 'r') | (primar == 'R'))
		offset = 16;
	else if ((primar == 'g') | (primar == 'G'))
		offset = 8;
	else if ((primar == 'b') | (primar == 'B'))
		offset = 0;

	start_color = (COLOR_START & (0x000000ff << offset)) >> offset;
	end_color = (COLOR_END & (0x000000ff << offset)) >> offset;
	
	new_primary_color = (end_color - start_color) * percent / 100;
	new_primary_color = start_color + new_primary_color;
	return (new_primary_color);
}

void	draw_pixel(t_fdf *fdf, int x, int y, int color)
{
	int	position;

	if (is_outise_screen(fdf, x, y))
		return ;
	position = y * fdf->img_sizel + x * fdf->img_bpp / 8;
	*(unsigned int *)(fdf->img_addr + position) = color;
}

int	is_outise_screen(t_fdf *fdf, int x, int y)
{
	int	xmax;
	int	ymax;

	xmax = fdf->img_sizel / (fdf->img_bpp / 8);
	ymax = fdf->img_size_y;
	if (x < 0 || y < 0 || x > xmax || y > ymax)
		return (1);
	return (0);
}
