/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   ft_split_quotes.c                                  :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: lperrey <lperrey@student.42.fr>            +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2021/11/13 07:08:40 by lperrey           #+#    #+#             */
/*   Updated: 2021/11/26 21:27:10 by lperrey          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "minishell.h"

static size_t	count_word(char const *s, char c);
static char		**alloc_words(char const *s, char c, char **str_arr,
					size_t words_count);
static void		fill_arr(char const *s, char c, char **str_arr);
static int		quote_state_change(int *quote_state, const char *s);

char	**ft_split_quotes(char const *s, char c)
{
	char	**str_arr;
	size_t	words_count;

	if (s == NULL)
		return (NULL);
	words_count = count_word(s, c);
	str_arr = ft_calloc(words_count + 1, sizeof(char *));
	if (!str_arr)
		return (NULL);
	if (!(alloc_words(s, c, str_arr, words_count)))
	{
		ft_free_2d_arr(str_arr);
		return (NULL);
	}
	fill_arr(s, c, str_arr);
	return (str_arr);
}

static size_t	count_word(char const *s, char c)
{
	unsigned int	i;
	size_t			count;
	int				quote_state;

	i = 0;
	count = 0;
	quote_state = 0;
	while (s[i])
	{
		while (s[i] == c)
			i++;
		if (s[i])
			count++;
		while (s[i] && (s[i] != c || quote_state))
		{
			while (quote_state_change(&quote_state, &s[i]))
				i++;
			if (s[i] && (s[i] != c || quote_state))
				i++;
		}
	}
	return (count);
}

static char	**alloc_words(char const *s, char c, char **str_arr,
				size_t words_count)
{
	unsigned int	i;
	size_t			len;
	unsigned int	arr_i;
	int				quote_state;

	i = 0;
	arr_i = 0;
	quote_state = 0;
	while (arr_i < words_count)
	{
		len = 0;
		while (s[i] == c)
			i++;
		while (s[i + len]
			&& (quote_state_change(&quote_state, &s[i + len])
				|| (s[i + len] != c || quote_state)))
			len++;
		i = i + len;
		str_arr[arr_i] = ft_calloc(len + 1, 1);
		if (!str_arr[arr_i])
			return (NULL);
		arr_i++;
	}
	return (str_arr);
}

// Plus clair, plus de 25 lignes :( 
/* static char	**alloc_words(char const *s, char c, char **str_arr,
				size_t words_count)
{
	unsigned int	i;
	size_t			len;
	unsigned int	arr_i;
	int				quote_state;

	i = 0;
	arr_i = 0;
	quote_state = 0;
	while (arr_i < words_count)
	{
		len = 0;
		while (s[i] == c)
			i++;
		while (s[i + len] && (s[i + len] != c || quote_state))
		{
			while (quote_state_change(&quote_state, &s[i + len]))
				len++;
			if (s[i + len] != c || quote_state)
				len++;
		}
		i = i + len;
		str_arr[arr_i] = ft_calloc(len + 1, 1);
		if (!str_arr[arr_i])
			return (NULL);
		arr_i++;
	}
	return (str_arr);
} */

static void	fill_arr(char const *s, char c, char **str_arr)
{
	unsigned int	i;
	unsigned int	arr_i;
	unsigned int	char_i;
	int				quote_state;

	i = 0;
	arr_i = 0;
	quote_state = 0;
	while (str_arr[arr_i])
	{
		while (s[i] == c)
			i++;
		char_i = 0;
		while (s[i] && (s[i] != c || quote_state))
		{
			while (quote_state_change(&quote_state, &s[i]))
				str_arr[arr_i][char_i++] = s[i++];
			if (s[i] && (s[i] != c || quote_state))
				str_arr[arr_i][char_i++] = s[i++];
		}
		str_arr[arr_i][char_i] = '\0'; //superflu si ft_calloc
		arr_i++;
	}
}

static int	quote_state_change(int *quote_state, const char *s)
{
	if (s[0] == '\'' && *quote_state != IN_DQUOTES)
	{
		if (*quote_state == IN_QUOTES)
			*quote_state = 0;
		else if (ft_strchr(&s[1], '\'')) // if closed quotes
			*quote_state = IN_QUOTES;
		else
			return (0);
		return (1);
	}
	else if (s[0] == '\"' && *quote_state != IN_QUOTES)
	{
		if (*quote_state == IN_DQUOTES)
			*quote_state = 0;
		else if (ft_strchr(&s[1], '\"')) // if closed quotes
			*quote_state = IN_DQUOTES;
		else
			return (0);
		return (1);
	}
	return (0);
}
