/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   u_init.c                                           :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: rbousset <marvin@42.fr>                    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2020/02/14 17:19:27 by rbousset          #+#    #+#             */
/*   Updated: 2020/02/14 17:19:29 by rbousset         ###   ########lyon.fr   */
/*                                                                            */
/* ************************************************************************** */

#include <unistd.h>
#include <stdlib.h>
#include <libft.h>
#include <signal.h>
#include <string.h>
#include <term.h>

#include "c_ctrls.h"
#include "c_init.h"
#include "c_keys.h"
#include "c_input.h"
#include "c_utils.h"
#include "b_exit.h"
#include "s_struct.h"
#include "s_com.h"
#include "s_line.h"
#include "s_destroy.h"
#include "m_prompt.h"
#include "m_loop.h"

short
	c_set_term_raw(char mode)
{
	struct termios tios;

	ft_memset(&tios, 0, sizeof(tios));
	tcgetattr(STDIN_FILENO, &tios);
	if (mode)
	{
		tios.c_lflag &= ~(ECHO | ICANON | ISIG);
		tios.c_oflag &= ~(OPOST);
		tios.c_cc[VMIN] = 1;
		tios.c_cc[VTIME] = 0;
	}
	else
	{
		tios.c_lflag |= (ECHO | ICANON | ISIG);
		tios.c_oflag |= (OPOST);
	}
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios);
	mode ? tputs(tgetstr("ns", NULL), 1, ft_putchar) : 0;
	return (1);
}

static void
	c_add_char(char **line, char *buf, t_caps *tcaps, t_msh *msh)
{
	*line = c_insert_char(*line, buf[0], tcaps);
	tcaps->cpos++;
	if ((((tcaps->cpos) + tcaps->plen) %
		tcaps->ws.ws_col) == 0)
	{
		write(1, "\n\r", 2);
		return ;
	}
	c_redraw_line(*line, tcaps, msh);
}

static short
	c_read_cap(char *buf, char *line, t_caps *tcaps, t_msh *msh)
{
	if (((*((unsigned int *)buf)) == LEFT_K) ||
		((*((unsigned int *)buf)) == CTRL_B))
		return (c_key_left(tcaps->plen, tcaps));
	else if (((*((unsigned int *)buf)) == RIGHT_K) ||
			((*((unsigned int *)buf)) == CTRL_F))
		return (c_key_right(ft_strlen(line), tcaps->plen, tcaps));
	else if (((*((unsigned int *)buf)) == HOME_K) ||
			((*((unsigned int *)buf)) == CTRL_A))
		return (c_home_key(tcaps->plen, tcaps));
	else if (((*((unsigned int *)buf)) == END_K) ||
			((*((unsigned int *)buf)) == CTRL_E))
		return (c_end_key(ft_strlen(line), tcaps->plen, tcaps));
	else if ((*((unsigned int *)buf)) == CTRL_L)
		return (c_ctrl_l(line, tcaps, msh));
	else if ((*((unsigned int *)buf)) == CTRL_D &&
			line[0] == '\0')
	{
		c_set_term_raw(0);
		write(2, "exit\n", 5);
		exit(msh->ret);
		return (1);
	}
	else
		return (0);
}

static char
	*c_process_key(char *buf, t_caps *tcaps, t_msh *msh)
{
	static char	*line = NULL;
	int			i;

	i = -1;
	if (line == NULL)
		if (!(line = ft_calloc(1, sizeof(char))))
			return (NULL);
	if (ft_isprint(buf[0]))
		c_add_char(&line, buf, tcaps, msh);
	else if ((*((unsigned int *)buf)) == DEL_K)
	{
		c_back_slash(&line, tcaps->plen, tcaps);
		if ((((tcaps->cpos) + tcaps->plen) %
			tcaps->ws.ws_col) == 0)
		{
			return (NULL);
		}
		c_redraw_line(line, tcaps, msh);
	}
	else if ((*((unsigned int *)buf)) == CTRL_C)
		return (c_ctrl_c(&line, buf, msh));
	else
		c_read_cap(buf, line, tcaps, msh);
	return ((buf[0] == '\n') ? c_new_line(line, tcaps) : NULL);
}

short
	c_gnl(int fd, char **line, char psx, t_msh *msh)
{
	t_caps	tcaps;
	char	nread[4];

	c_init_line(psx, &tcaps);
	tputs(tgetstr("cr", NULL), 1, ft_putchar);
	m_prompt_psx(psx, msh);
	ft_bzero(nread, 4);
	msh->sig = 0;
	tcaps.plen = (unsigned int)m_plen(msh->ps[psx - 1]);
	if (!(c_get_win_size(&tcaps.ws)))
		return (-1);
	while (!(ft_strchr(nread, '\n')))
	{
		ft_bzero(nread, 4);
		if (!(read(fd, nread, 3)))
			return (0);
		else
			*line = c_process_key(nread, &tcaps, msh);
		tputs(tgetstr("ve", NULL), 1, ft_putchar);
	}
	return (1);
}