/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <ctype.h>
#include "shell_ops.h"
#include "shell_help.h"
#include "shell_utils.h"


/* Function prints a string on terminal screen with requested margin.
 * It takes care to not divide words.
 *   shell		Pointer to shell instance.
 *   p_str		Pointer to string to be printed.
 *   terminal_offset	Requested left margin.
 *   offset_first_line	Add margin to the first printed line.
 */
static void formatted_text_print(const struct shell *sh, const char *str,
				 size_t terminal_offset, bool offset_first_line)
{
	size_t offset = 0;
	size_t length;

	if (str == NULL) {
		return;
	}

	if (offset_first_line) {
		z_shell_op_cursor_horiz_move(sh, terminal_offset);
	}


	/* Skipping whitespace. */
	while (isspace((int) *(str + offset)) != 0) {
		++offset;
	}

	while (true) {
		size_t idx = 0;
		bool newline_found = false;

		length = z_shell_strlen(str) - offset;

		if (length <=
		    sh->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) {
			for (idx = 0; idx < length; idx++) {
				if (*(str + offset + idx) == '\n') {
					z_transport_buffer_flush(sh);
					z_shell_write(sh, str + offset, idx);
					offset += idx + 1;
					z_cursor_next_line_move(sh);
					z_shell_op_cursor_horiz_move(sh,
							terminal_offset);
					newline_found = true;
					break;
				}
			}

			/* If we found a newline, continue processing the remaining text */
			if (newline_found) {
				continue;
			}

			/* String will fit in one line. */
			z_shell_raw_fprintf(sh->fprintf_ctx, str + offset);

			break;
		}

		/* String is longer than terminal line so text needs to
		 * divide in the way to not divide words.
		 */
		length = sh->ctx->vt100_ctx.cons.terminal_wid
				- terminal_offset;

		while (true) {
			/* Determining line break. */
			if (isspace((int) (*(str + offset + idx))) != 0) {
				length = idx;
				if (*(str + offset + idx) == '\n') {
					break;
				}
			}

			if ((idx + terminal_offset) >=
			    sh->ctx->vt100_ctx.cons.terminal_wid) {
				/* End of line reached. */
				break;
			}

			++idx;
		}

		/* Writing one line, fprintf IO buffer must be flushed
		 * before calling shell_write.
		 */
		z_transport_buffer_flush(sh);
		z_shell_write(sh, str + offset, length);
		offset += length;

		/* Calculating text offset to ensure that next line will
		 * not begin with a space.
		 */
		while (isspace((int) (*(str + offset))) != 0) {
			++offset;
		}

		z_cursor_next_line_move(sh);
		z_shell_op_cursor_horiz_move(sh, terminal_offset);

	}
	z_cursor_next_line_move(sh);
}

static void formatted_structured_help_print(const struct shell *sh, const char *item_name,
					    const char *item_help, size_t terminal_offset)
{
	const struct shell_cmd_help *structured = (const struct shell_cmd_help *)item_help;

	if (structured->description) {
		formatted_text_print(sh, structured->description, terminal_offset, false);
	}

	if (structured->usage) {
		z_shell_op_cursor_horiz_move(sh, terminal_offset);
		z_shell_fprintf(sh, SHELL_NORMAL, "Usage: %s ", item_name);
		formatted_text_print(sh, structured->usage, terminal_offset + 7, false);
	}
}

static void help_item_print(const struct shell *sh, const char *item_name,
			    uint16_t item_name_width, const char *item_help)
{
	static const uint8_t tabulator[] = "  ";
	static const char sub_cmd_sep[] = ": "; /* subcommands separator */
	const uint16_t offset = 2 * strlen(tabulator) + item_name_width + strlen(sub_cmd_sep);

	if ((item_name == NULL) || (item_name[0] == '\0')) {
		return;
	}

	if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) &&
	    !IS_ENABLED(CONFIG_NATIVE_LIBC)) {
		/* print option name */
		z_shell_fprintf(sh, SHELL_NORMAL, "%s%-*s", tabulator,
				item_name_width, item_name);
	} else {
		uint16_t tmp = item_name_width - strlen(item_name);
		char space = ' ';

		z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", tabulator,
				item_name);

		if (item_help) {
			for (uint16_t i = 0; i < tmp; i++) {
				z_shell_write(sh, &space, 1);
			}
		}
	}

	if (item_help == NULL) {
		z_cursor_next_line_move(sh);
		return;
	} else {
		z_shell_fprintf(sh, SHELL_NORMAL, "%s: ", tabulator);
	}
	/* print option help */
	if (shell_help_is_structured(item_help)) {
		formatted_structured_help_print(sh, item_name, item_help, offset);
	} else {
		formatted_text_print(sh, item_help, offset, false);
	}
}

/* Function prints all subcommands of the parent command together with their
 * help string
 */
void z_shell_help_subcmd_print(const struct shell *sh,
			       const struct shell_static_entry *parent,
			       const char *description)
{
	const struct shell_static_entry *entry = NULL;
	struct shell_static_entry dloc;
	uint16_t longest = 0U;
	size_t idx = 0;

	/* Searching for the longest subcommand to print. */
	while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) {
		longest = max(longest, z_shell_strlen(entry->syntax));
	}

	/* No help to print */
	if (longest == 0) {
		return;
	}

	if (description != NULL) {
		z_shell_fprintf(sh, SHELL_NORMAL, description);
	}

	/* Printing subcommands and help string (if exists). */
	idx = 0;

	while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) {
		help_item_print(sh, entry->syntax, longest, entry->help);
	}
}

void z_shell_help_cmd_print(const struct shell *sh,
			    const struct shell_static_entry *cmd)
{
	static const char cmd_sep[] = " - "; /* commands separator */
	uint16_t field_width;

	field_width = z_shell_strlen(cmd->syntax) + z_shell_strlen(cmd_sep);

	z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", cmd->syntax, cmd_sep);

	if (shell_help_is_structured(cmd->help)) {
		formatted_structured_help_print(sh, cmd->syntax, cmd->help, field_width);
	} else {
		formatted_text_print(sh, cmd->help, field_width, false);
	}
}

bool z_shell_help_request(const char *str)
{
	if (!IS_ENABLED(CONFIG_SHELL_HELP_OPT_PARSE)) {
		return false;
	}

	if (!strcmp(str, "-h") || !strcmp(str, "--help")) {
		return true;
	}

	return false;
}
