/*
 * 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 *shell, 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(shell, terminal_offset);
	}


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

	while (true) {
		size_t idx = 0;

		length = z_shell_strlen(str) - offset;

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

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

			break;
		}

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

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

			if ((idx + terminal_offset) >=
			    shell->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(shell);
		z_shell_write(shell, str + offset, length);
		offset += length;

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

		z_cursor_next_line_move(shell);
		z_shell_op_cursor_horiz_move(shell, terminal_offset);

	}
	z_cursor_next_line_move(shell);
}

static void help_item_print(const struct shell *shell, const char *item_name,
			    uint16_t item_name_width, const char *item_help)
{
	static const uint8_t tabulator[] = "  ";
	const uint16_t offset = 2 * strlen(tabulator) + item_name_width + 1;

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

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

		z_shell_fprintf(shell, SHELL_NORMAL, "%s%s", tabulator,
				item_name);
		for (uint16_t i = 0; i < tmp; i++) {
			z_shell_write(shell, &space, 1);
		}
		z_shell_fprintf(shell, SHELL_NORMAL, "%s:", tabulator);
	}

	if (item_help == NULL) {
		z_cursor_next_line_move(shell);
		return;
	}
	/* print option help */
	formatted_text_print(shell, 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 *shell,
			       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 = Z_MAX(longest, z_shell_strlen(entry->syntax));
	}

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

	if (description != NULL) {
		z_shell_fprintf(shell, 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(shell, entry->syntax, longest, entry->help);
	}
}

void z_shell_help_cmd_print(const struct shell *shell,
			    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(shell, SHELL_NORMAL, "%s%s", cmd->syntax, cmd_sep);

	formatted_text_print(shell, 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;
}
