/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   ft_printf.c                                        :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: thrieg <thrieg@student.42mulhouse.fr>      +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2024/10/21 18:24:04 by thrieg            #+#    #+#             */
/*   Updated: 2025/02/16 19:08:03 by thrieg           ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "../libft.h"
#include "ft_printf.h"

int	ft_case_c(t_vector *vec, va_list *args);
int	ft_case_percent(t_vector *vec);
int	ft_case_s(t_vector *vec, va_list *args);
int	ft_case_p(t_vector *vec, va_list *args);
int	ft_case_u(t_vector *vec, va_list *args);
int	ft_case_x(t_vector *vec, va_list *args);
int	ft_case_upperx(t_vector *vec, va_list *args);
int	ft_case_d(t_vector *vec, va_list *args);
int	ft_case_i(t_vector *vec, va_list *args);
int	handle_percent_bonus(const char *str, t_vector *vec, va_list *args);

//properly frees the vector and return string
void	ft_cleanup(t_vector **vec, va_list *args)
{
	ft_free_vector(vec);
	va_end(*args);
}

//returns the number of characters to skip after the % sign
//or 0 if something goes wrong
int	handle_percent(const char *str, t_vector *vec, va_list *args)
{
	if (str[0] == '%' && str[1] == 'c')
		return (ft_case_c(vec, args));
	if (str[0] == '%' && str[1] == '%')
		return (ft_case_percent(vec));
	if (str[0] == '%' && str[1] == 's')
		return (ft_case_s(vec, args));
	if (str[0] == '%' && str[1] == 'p')
		return (ft_case_p(vec, args));
	if (str[0] == '%' && str[1] == 'u')
		return (ft_case_u(vec, args));
	if (str[0] == '%' && str[1] == 'x')
		return (ft_case_x(vec, args));
	if (str[0] == '%' && str[1] == 'X')
		return (ft_case_upperx(vec, args));
	if (str[0] == '%' && (str[1] == 'd'))
		return (ft_case_d(vec, args));
	if (str[0] == '%' && (str[1] == 'i'))
		return (ft_case_i(vec, args));
	return (handle_percent_bonus(str, vec, args));
}

static int	ft_parsing_loop(
t_vector *return_vector,
const char *str,
va_list *args
)
{
	char	*next_percent;
	int		nb_character;

	while (*str)
	{
		next_percent = ft_strchr(str, '%');
		if (!next_percent)
		{
			next_percent = ft_strchr(str, '\0');
			if (!ft_vector_concat(return_vector, str, (next_percent - str)))
				return (0);
			return (1);
		}
		if (!ft_vector_concat(return_vector, str, (next_percent - str)))
			return (0);
		str = next_percent;
		nb_character = handle_percent(str, return_vector, args);
		if (!nb_character)
			return (0);
		str += nb_character;
		str++;
	}
	return (1);
}

//returns the number of characters written or -1 on errors
int	ft_printf(const char *str, ...)
{
	int			nb_character;
	t_vector	*return_vector;
	va_list		args;

	if (!str)
		return (-1);
	va_start(args, str);
	return_vector = ft_create_vector(2);
	if (!return_vector)
		return (-1);
	if (!ft_parsing_loop(return_vector, str, &args))
		return (ft_cleanup(&return_vector, &args), -1);
	nb_character = write(1, return_vector->buffer, return_vector->index);
	return (ft_cleanup(&return_vector, &args), nb_character);
}

//returns the number of characters written or -1 on errors
int	ft_dprintf(int fd, const char *str, ...)
{
	int			nb_character;
	t_vector	*return_vector;
	va_list		args;

	if (!str)
		return (-1);
	va_start(args, str);
	return_vector = ft_create_vector(2);
	if (!return_vector)
		return (-1);
	if (!ft_parsing_loop(return_vector, str, &args))
		return (ft_cleanup(&return_vector, &args), -1);
	nb_character = write(fd, return_vector->buffer, return_vector->index);
	return (ft_cleanup(&return_vector, &args), nb_character);
}
