/*
 * Copyright (c) 2018 Oticon A/S
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <ctype.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/console/console.h>
#include "posix_board_if.h"
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>

#define DEBUG_ECHO 0

#if (DEBUG_ECHO)
#define ECHO(...) printf(__VA_ARGS__)
#else
#define ECHO(...)
#endif

#if defined(CONFIG_NATIVE_POSIX_STDOUT_CONSOLE)
/**
 *
 * @brief Initialize the driver that provides the printk output
 *
 */
static void native_posix_stdout_init(void)
{
	/* Let's ensure that even if we are redirecting to a file, we get stdout
	 * and stderr line buffered (default for console). Note that glibc
	 * ignores size. But just in case we set a reasonable number in case
	 * somebody tries to compile against a different library
	 */
	setvbuf(stdout, NULL, _IOLBF, 512);
	setvbuf(stderr, NULL, _IOLBF, 512);

	extern void __printk_hook_install(int (*fn)(int));
	__printk_hook_install(putchar);
}

/**
 * Ensure that whatever was written thru printk is displayed now
 */
void posix_flush_stdout(void)
{
	fflush(stdout);
}
#endif /* CONFIG_NATIVE_POSIX_STDOUT_CONSOLE */

#if defined(CONFIG_NATIVE_POSIX_STDIN_CONSOLE)

#define VALID_DIRECTIVES \
	"Valid native console driver directives:\n" \
	"  !wait %%u\n" \
	"  !quit\n"

static struct k_fifo *avail_queue;
static struct k_fifo *lines_queue;
static uint8_t (*completion_cb)(char *line, uint8_t len);
static bool stdin_is_tty;

static K_KERNEL_STACK_DEFINE(stack, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
static struct k_thread native_stdio_thread;

static inline void found_eof(void)
{
	/*
	 * Once stdin is closed or the input file has ended,
	 * there is no need to try again
	 */
	ECHO("Got EOF\n");
	k_thread_abort(&native_stdio_thread);
}

/*
 * Check if the command is a directive the driver handles on its own
 * and if it is, handle it.
 * If not return 0 (so it can be passed to the shell)
 *
 * Inputs
 *   s       Command string
 *   towait  Pointer to the amount of time wait until attempting to receive
 *           the next command
 *
 * return 0 if it is not a directive
 * return > 0 if it was a directive (command starts with '!')
 * return 2 if the driver directive requires to pause processing input
 */
static int catch_directive(char *s, int32_t *towait)
{
	while (*s != 0  && isspace(*s)) {
		s++;
	}

	if (*s != '!') {
		return 0;
	}

	if (strncmp(s, "!wait", 5) == 0) {
		int ret;

		ret = sscanf(&s[5], "%i", towait);
		if (ret != 1) {
			posix_print_error_and_exit("%s(): '%s' not understood, "
						   "!wait syntax: !wait %%i\n",
						   __func__, s);
		}
		return 2;
	} else if (strcmp(s, "!quit") == 0) {
		posix_exit(0);
	}

	posix_print_warning("%s(): '%s' not understood\n" VALID_DIRECTIVES,
			    __func__, s);

	return 1;
}

/**
 * Check if there is data ready in stdin
 */
static int stdin_not_ready(void)
{
	int ready;
	fd_set readfds;
	struct timeval timeout;

	timeout.tv_usec = 0;
	timeout.tv_sec  = 0;

	FD_ZERO(&readfds);
	FD_SET(STDIN_FILENO, &readfds);

	ready = select(STDIN_FILENO+1, &readfds, NULL, NULL, &timeout);

	if (ready == 0) {
		return 1;
	} else if (ready == -1) {
		posix_print_error_and_exit("%s: Error on select ()\n",
					   __func__);
	}

	return 0;
}

/**
 * Check if there is any line in the stdin buffer,
 * if there is and we have available shell buffers feed it to the shell
 *
 * This function returns how long the thread should wait in ms,
 * before checking again the stdin buffer
 */
static int32_t attempt_read_from_stdin(void)
{
	static struct console_input *cmd;
	int32_t towait = CONFIG_NATIVE_STDIN_POLL_PERIOD;

	while (1) {
		char *ret;
		int last;
		int is_directive;

		if (feof(stdin)) {
			found_eof();
		}

		/*
		 * If stdin comes from a terminal, we check if the user has
		 * input something, and if not we pause the process.
		 *
		 * If stdin is not coming from a terminal, but from a file or
		 * pipe, we always proceed to try to get data and block until
		 * we do
		 */
		if (stdin_is_tty && stdin_not_ready()) {
			return towait;
		}

		/* Pick next available shell line buffer */
		if (!cmd) {
			cmd = k_fifo_get(avail_queue, K_NO_WAIT);
			if (!cmd) {
				return towait;
			}
		}

		/*
		 * By default stdin is (_IOLBF) line buffered when connected to
		 * a terminal and fully buffered (_IOFBF) when connected to a
		 * pipe/file.
		 * If we got a terminal: we already checked for it to be ready
		 * and therefore a full line should be there for us.
		 *
		 * If we got a pipe or file we will block until we get a line,
		 * or we reach EOF
		 */
		ret = fgets(cmd->line, CONSOLE_MAX_LINE_LEN, stdin);
		if (ret == NULL) {
			if (feof(stdin)) {
				found_eof();
			}
			/*
			 * Otherwise this was an unexpected error we do
			 * not try to handle
			 */
			return towait;
		}

		/* Remove a possible end of line and other trailing spaces */
		last = (int)strlen(cmd->line) - 1;
		while ((last >= 0) && isspace(cmd->line[last])) {
			cmd->line[last--] = 0;
		}

		ECHO("Got: \"%s\"\n", cmd->line);

		/*
		 * This console has a special set of directives which start with
		 * "!" which we capture here
		 */
		is_directive = catch_directive(cmd->line, &towait);
		if (is_directive == 2) {
			return towait;
		} else if (is_directive > 0) {
			continue;
		}

		/* Let's give it to the shell to handle */
		k_fifo_put(lines_queue, cmd);
		cmd = NULL;
	}

	return towait;
}

/**
 * This thread will check if there is any new line in the stdin buffer
 * every CONFIG_NATIVE_STDIN_POLL_PERIOD ms
 *
 * If there is, it will feed it to the shell
 */
static void native_stdio_runner(void *p1, void *p2, void *p3)
{
	stdin_is_tty = isatty(STDIN_FILENO);

	while (1) {
		int32_t wait_time = attempt_read_from_stdin();

		k_sleep(wait_time);
	}
}
#endif /* CONFIG_NATIVE_POSIX_STDIN_CONSOLE */

static int native_posix_console_init(const struct device *arg)
{
	ARG_UNUSED(arg);

#if defined(CONFIG_NATIVE_POSIX_STDOUT_CONSOLE)
	native_posix_stdout_init();
#endif

	return 0;
}

SYS_INIT(native_posix_console_init, PRE_KERNEL_1,
	CONFIG_NATIVE_POSIX_CONSOLE_INIT_PRIORITY);
