#include "parsing_private.h"
#include <stddef.h>

char	**get_body(const char **file_content, size_t header_size)
{
	char	**body;
	size_t	i;
	size_t	len;

	len = 0;
	while (file_content[header_size + len] != NULL)
		len++;
	body = malloc((len + 1) * sizeof(char *));
	if (body == NULL)
		return (NULL);
	body[len] = NULL;
	i = 0;
	while (i < len)
	{
		body[i] = ft_strdup(file_content[header_size + i]);
		if (body[i] == NULL)
		{
			ft_cancel((void **) body, i);
			return (NULL);
		}
		i++;
	}
	return (body);
}

int	get_spawn_position(const char **body, double *spawn_x, double *spawn_y)
{
	size_t	x;
	size_t	y;

	*spawn_x = -1;
	*spawn_y = -1;
	y = 0;
	while (body[y] != NULL)
	{
		x = 0;
		while (body[y][x] != '\0')
		{
			if (ft_is_in("NSEW", body[y][x]))
			{
				if (*spawn_x != -1)
					return (1);
				*spawn_x = x;
				*spawn_y = y;
			}
			x++;
		}
		y++;
	}
	if (*spawn_x == -1)
		return (2);
	return (0);
}

static int	map_is_in_one_part(const char **body)
{
	size_t	y;

	y = ft_tablen((const void **) body) - 1;
	while (body[y][0] == '\0' || ft_contain_only(body[y], ' '))
		y--;
	while (y > 0)
	{
		if (body[y][0] == '\0' || ft_contain_only(body[y], ' '))
			return (1);
		y--;
	}
	return (0);
}

static int	map_surround(const char **body)
{
	size_t	y;
	size_t	x;

	y = 0;
	while (body[y] != NULL)
	{
		x = 0;
		while (body[y][x] != '\0')
		{
			if (body[y][x] == '0')
			{
				if (body[y + 1] == NULL || (y == 0)
					|| (body[y][x + 1] == '\0') || (x == 0)
					|| (body[y + 1][x] == ' ' || body[y + 1][x] == '\0')
					|| (body[y - 1][x] == ' ' || body[y - 1][x] == '\0')
					|| (body[y][x - 1] == ' ' || body[y][x - 1] == '\0')
					|| (body[y][x + 1] == ' ' || body[y][x + 1] == '\0'))
					return (1);
			}
			x++;
		}
		y++;
	}
	return (0);
}

static int	body_contain_normal_char(const char **body)
{
	unsigned int	y;
	unsigned int	x;

	y = 0;
	while (body[y] != NULL)
	{
		x = 0;
		while (body[y][x] != '\0')
		{
			if (!ft_is_in(" 01NEWS", body[y][x]))
			{
				ft_eprintf("map: %c: invalid character at rows=%u, colums=%u", body[y][x], y, x);
				return (0);
			}
			x++;
		}
		y++;
	}
	return (1);
}

void	get_size(const char **body, t_map *map)
{
	size_t	y;
	size_t	x;

	map->size_x = 0;
	y = 0;
	while (body[y] != NULL)
	{
		x = ft_strlen(body[y]);
		if (x > map->size_x)
			map->size_x = x;
		y++;
	}
	map->size_y = y;
}

int	body_is_valid(const char **body, t_map *map)
{
	int	error;

	if (body == NULL)
		return (0);
	error = get_spawn_position(body, &map->ply_x, &map->ply_y);
	if (error == 1)
	{
		ft_eprintf("map: spawn position: multiple definition");
		return (0);
	}
	else if (error == 2)
	{
		ft_eprintf("map: spawn position: not define");
		return (0);
	}
	error = map_surround(body);
	if (error)
	{
		ft_eprintf("map: not surrounded");
		return (0);
	}
	error = map_is_in_one_part(body);
	if (error)
	{
		ft_eprintf("map: splitted");
		return (0);
	}
	if (body_contain_normal_char(body) == 0)
		return (0);
	get_size(body, map);
	return (1);
}
