/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   parser_words.c                                     :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: sede-san <sede-san@student.42madrid.com    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2026/02/13 21:29:44 by sede-san          #+#    #+#             */
/*   Updated: 2026/02/14 03:34:38 by sede-san         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "parser.h"

void	command_clear_argv(t_command *command);

static bool	args_add_word(
	t_list **args,
	const char *value
)
{
	t_list	*node;
	char	*dup;

	dup = ft_strdup(value);
	if (dup == NULL)
		return (false);
	node = ft_lstnew(dup);
	if (node == NULL)
		return (free(dup), false);
	ft_lstadd_back(args, node);
	return (true);
}

static bool	command_append_words(
	t_command *command,
	t_list **args,
	int new_argc
)
{
	char	**argv;
	t_list	*current;
	int		i;

	argv = (char **)malloc(sizeof(char *) * (command->argc + new_argc + 1));
	if (argv == NULL)
		return (false);
	i = 0;
	while (i < command->argc)
	{
		argv[i] = command->argv[i];
		i++;
	}
	current = *args;
	while (current != NULL)
	{
		argv[i++] = (char *)current->content;
		current = current->next;
	}
	argv[i] = NULL;
	free(command->argv);
	ft_lstclear_nodes(args);
	command->argv = argv;
	command->argc += new_argc;
	return (true);
}

/**
 * @brief Adds all consecutive word tokens to a command's argv and updates its
 *        argc accordingly.
 *
 * @param command The command to add the word tokens to.
 * @param tokens  The list of tokens to add to the command.
 */
void	words_add(
	t_list **tokens,
	t_command **command
)
{
	t_list	*args;
	t_list	*arg;
	t_token	*token;
	t_token	*next_token;
	int		new_argc;
	size_t	i;
	bool	is_fd_prefix;

	args = NULL;
	new_argc = 0;
	arg = *tokens;
	token = (t_token *)arg->content;
	while (arg != NULL && token->type == TOKEN_WORD)
	{
		is_fd_prefix = false;
		if (arg->next != NULL && token->value != NULL
			&& token->value[0] != '\0')
		{
			next_token = (t_token *)arg->next->content;
			i = 0;
			while (token->value[i] != '\0' && ft_isdigit(token->value[i]))
				i++;
			is_fd_prefix = (token->value[i] == '\0' && is_redirection(next_token));
		}
		if (is_fd_prefix)
			break ;
		if (!args_add_word(&args, token->value))
			return (ft_lstclear(&args, free), command_clear(*command),
				*command = NULL, (void)0);
		new_argc++;
		arg = arg->next;
		if (arg != NULL)
			token = (t_token *)arg->content;
	}
	*tokens = arg;
	if (!command_append_words(*command, &args, new_argc))
		return (ft_lstclear(&args, free), command_clear(*command),
			*command = NULL, (void)0);
}

void	command_clear_argv(
	t_command *command
)
{
	int	i;

	if (command->argv != NULL)
	{
		i = 0;
		while (i < command->argc)
		{
			free(command->argv[i]);
			i++;
		}
		free(command->argv);
		command->argv = NULL;
	}
}

/**
 * @brief Clears a command, freeing all associated memory.
 *
 * @param command The command to clear.
 */
void	command_clear(
	t_command *command
)
{
	if (command != NULL)
	{
		command_clear_argv(command);
		ft_lstclear(&command->redirections,
			(void (*)(void *))redirection_clear);
		ft_lstclear(&command->heredocs, (void (*)(void *))redirection_clear);
		free(command);
	}
}
