/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   shaders.c                                          :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: qmennen <qmennen@student.codam.nl>         +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2025/05/08 18:27:59 by qmennen           #+#    #+#             */
/*   Updated: 2025/06/03 19:34:08 by qmennen          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "cub3d.h"
#include "glad.h"
#include "MLX42_Int.h"

void	set_uniforms(t_game *game)
{
	mlx_ctx_t	*ctx;

	ctx = (mlx_ctx_t *)game->screen->mlx->context;
	glUniform1f(game->screen->u_time_location, (float)mlx_get_time());
	glUniform1f(game->screen->u_battery_location, game->player->battery);
	glUniform2f(game->screen->u_resolution_location,
		(float)game->screen->width, (float)game->screen->height);
	glUniform1f(game->screen->u_hit_timer_location, game->player->hit_timer);
	glUniform1i(game->screen->u_enabled_location,
		game->manager->state == GAME_STATE_PLAYING);
}

int	load_uniforms(t_game **game)
{
	mlx_ctx_t	*ctx;

	ctx = (mlx_ctx_t *)(*game)->screen->mlx->context;
	(*game)->screen->u_time_location = glGetUniformLocation(ctx->shaderprogram, "u_time");
	(*game)->screen->u_battery_location = glGetUniformLocation(ctx->shaderprogram, "u_battery");
	(*game)->screen->u_hit_timer_location = glGetUniformLocation(ctx->shaderprogram, "u_hit_timer");
	(*game)->screen->u_enabled_location = glGetUniformLocation(ctx->shaderprogram, "u_enabled");
	(*game)->screen->u_resolution_location = glGetUniformLocation(ctx->shaderprogram, "u_resolution");
	if ((*game)->screen->u_time_location < 0 ||
		(*game)->screen->u_battery_location < 0 ||
		(*game)->screen->u_hit_timer_location < 0 ||
		(*game)->screen->u_enabled_location < 0 ||
		(*game)->screen->u_resolution_location < 0)
		return (FAILURE);
	return (SUCCESS);
}

static const char	*read_vertex_shader(void)
{
	const char	*target = "./assets/shaders/vert.glsl";
	char		*shader;
	int			fd;
	int			file_size;
	size_t		bytes_read;

	file_size = get_file_size(target);
	fd = open(target, O_RDONLY);
	if (fd < 0)
		return (perror("Error opening shader file"), NULL);
	shader = malloc(file_size * sizeof(char) + 1);
	if (!shader)
	{
		return (perror("Error allocating memory for shader"), close(fd), NULL);
	}
	bytes_read = read(fd, shader, file_size);
	if (bytes_read < 0)
	{
		return (perror("Error reading shader file"),
			free(shader), close(fd), NULL);
	}
	shader[bytes_read] = '\0';
	return (close(fd), shader);
}

static const char	*read_fragment_shader(void)
{
	const char	*target = "./assets/shaders/frag.glsl";
	char		*shader;
	int			fd;
	int			file_size;
	size_t		bytes_read;

	file_size = get_file_size(target);
	fd = open(target, O_RDONLY);
	if (fd < 0)
	{
		return (perror("Error opening shader file"), NULL);
	}
	shader = malloc(file_size * sizeof(char) + 1);
	if (!shader)
	{
		return (perror("Error allocating memory for shader"), close(fd), NULL);
	}
	bytes_read = read(fd, shader, file_size);
	if (bytes_read < 0)
	{
		return (perror("Error reading shader file"),
			free(shader), close(fd), NULL);
	}
	shader[bytes_read] = '\0';
	return (close(fd), shader);
}

int	shader_init(t_game **game)
{
	vert_shader = read_vertex_shader();
	if (!vert_shader)
		return (FAILURE);
	frag_shader = read_fragment_shader();
	if (!frag_shader)
		return (FAILURE);
	return (SUCCESS);
}
