/*
 * 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;

		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);
					break;
				}
			}

			/* 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 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[] = "  ";
	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(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 */
	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 = Z_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);

	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;
}
