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

#include "data/data.h"
#include "execution/execution.h"
#include "libftx/libft/libft.h"
#include "libftx/libft/list.h"
#include "libftx/libftx.h"
#include "minishell.h"
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>

static char	*ft_get_user_input()
{
	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	*content;
	int		exit_status;

	current = *data->cmds;
	while (current != NULL)
	{
		content = current->content;
		if (content->own_cmd == 0 && content->pid != -1)
		{
			waitpid(content->pid, &exit_status, 0);
			if (WIFSIGNALED(exit_status))
			{
				if (WTERMSIG(exit_status) == SIGKILL)
					data->exit_code = 131;
				else //(WTERMSIG(exit_status) == SIGINT)
					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);
}

void	ft_ctrlc(int num)
{
	t_data	*data;

	if (num == SIGQUIT)
		return ;
	data = ft_get_data();
	data->exit_code = 130;
	if (*ft_get_heredoc() != -1)
	{
		close(*ft_get_heredoc());
		*ft_get_heredoc() = -1;
	}
	else
	{
		if (data->child_pid > 1)
		{
			data->child_pid = 0;
			ft_putchar_fd('\n', 1);
		}
		else
		{
			rl_replace_line("", 0);
			rl_on_new_line();
			ft_putchar_fd('\n', 1);
			rl_redisplay();
		}
	}
}

void	ft_quit(int num)
{
	t_data	*data;

	(void) num;
	data = ft_get_data();
	data->exit_code = 131;
	if (data->child_pid > 1)
	{
		ft_printf("Quit (core dumped)\n");
		data->child_pid = 0;
	}
	else
	{
		rl_replace_line("", 0);
		rl_redisplay();
	}
}

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();
	data->exit_code = 0;
	data->child_pid = 0;
	data->cmds = malloc(sizeof(t_cmd *));
	if (data->cmds == NULL)
		return (1);
	*data->cmds = NULL;
	data->env = init_env(env);
	if (data->env == NULL)
		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);
}
