/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   main.c                                             :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: cchauvet <cchauvet@student.42angoulem      +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2023/02/16 15:16:14 by cchauvet          #+#    #+#             */
/*   Updated: 2023/03/30 13:12:41 by cchauvet         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "data/data.h"
#include "env/env.h"
#include "libftx/libftx.h"
#include "minishell.h"

static char	*ft_get_user_input(void)
{
	char	*line;
	char	*prompt;
	char	*pwd;

	pwd = get_pwd(2);
	if (pwd == NULL)
		return (NULL);
	prompt = ft_strmerger(2, pwd, "$ ");
	free(pwd);
	if (prompt == NULL)
	{
		ft_eprintf("minishell: malloc failed\n");
		return (NULL);
	}
	line = readline(prompt);
	if (line != NULL && ft_strcmp(line, "") != 0)
		add_history(line);
	free(prompt);
	if (line == NULL)
		ft_printf("exit\n");
	return (line);
}

static void	ft_cmds_waiter(t_data *data)
{
	t_list	*current;
	t_cmd	*cmd;
	int		exit_status;

	current = *data->cmds;
	while (current != NULL)
	{
		cmd = current->content;
		if (cmd->executable != NULL && cmd->own_cmd == 0
			&& cmd->pid != -1 && cmd->fd_in[0] != -2 && cmd->fd_out[0] != -2)
		{
			waitpid(cmd->pid, &exit_status, 0);
			if (WIFSIGNALED(exit_status))
			{
				if (WTERMSIG(exit_status) == SIGKILL)
					data->exit_code = 131;
				else
					data->exit_code = 130;
			}
			else
				data->exit_code = WEXITSTATUS(exit_status);
		}
		current = current->next;
	}
	data->child_pid = 0;
}

static int	ft_minishell(t_data *data, char *line)
{
	char	*line_clean;

	if (ft_syntax_verif(data, line))
		return (0);
	line_clean = ft_formater(data, line);
	if (line_clean == NULL || line_clean[0] == '\0')
		return (0);
	if (ft_cmds_parser(data, line_clean))
	{
		free(line_clean);
		return (0);
	}
	free(line_clean);
	if (ft_cmds_executor(data) == 1)
		return (1);
	ft_cmds_waiter(data);
	ft_lstclear(data->cmds, ft_cmddel);
	return (0);
}

int	ft_init_data(t_data *data, char **env)
{
	data->exit_code = 0;
	data->child_pid = 0;
	data->cmds = malloc(sizeof(t_cmd *));
	if (data->cmds == NULL)
	{
		ft_eprintf("minishell: malloc failed\n");
		return (1);
	}
	*data->cmds = NULL;
	data->env = init_env(env);
	if (data->env == NULL)
	{
		ft_eprintf("minishell: malloc failed\n");
		free(data->cmds);
		return (1);
	}
	return (0);
}

int	main(int ac, char **av, char **env)
{
	t_data	*data;
	char	*line;

	(void) ac;
	(void) av;
	signal(SIGINT, ft_ctrlc);
	signal(SIGQUIT, ft_quit);
	data = ft_get_data();
	if (ft_init_data(data, env))
		return (1);
	line = ft_get_user_input();
	while (line != NULL)
	{
		if (ft_minishell(data, line) == 1)
			break ;
		free(line);
		line = ft_get_user_input();
		if (line == NULL)
			break ;
	}
	ft_lstclear(data->cmds, ft_cmddel);
	free(data->cmds);
	ft_lstclear(data->env, env_del);
	free(data->env);
	return (data->exit_code);
}
