/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>
#include <fnmatch.h>
#include "shell_wildcard.h"
#include "shell_utils.h"


static void subcmd_get(const struct shell_cmd_entry *cmd,
		       size_t idx, const struct shell_static_entry **entry,
		       struct shell_static_entry *d_entry)
{
	__ASSERT_NO_MSG(entry != NULL);
	__ASSERT_NO_MSG(d_entry != NULL);

	if (cmd == NULL) {
		*entry = NULL;
		return;
	}

	if (cmd->is_dynamic) {
		cmd->u.dynamic_get(idx, d_entry);
		*entry = (d_entry->syntax != NULL) ? d_entry : NULL;
	} else {
		*entry = (cmd->u.entry[idx].syntax != NULL) ?
				&cmd->u.entry[idx] : NULL;
	}
}

static enum shell_wildcard_status command_add(char *buff, u16_t *buff_len,
					      char const *cmd,
					      char const *pattern)
{
	u16_t cmd_len = shell_strlen(cmd);
	char *completion_addr;
	u16_t shift;

	/* +1 for space */
	if ((*buff_len + cmd_len + 1) > CONFIG_SHELL_CMD_BUFF_SIZE) {
		return SHELL_WILDCARD_CMD_MISSING_SPACE;
	}

	completion_addr = strstr(buff, pattern);

	if (!completion_addr) {
		return SHELL_WILDCARD_CMD_NO_MATCH_FOUND;
	}

	shift = shell_strlen(completion_addr);

	/* make place for new command: + 1 for space + 1 for EOS */
	memmove(completion_addr + cmd_len + 1, completion_addr, shift + 1);
	memcpy(completion_addr, cmd, cmd_len);
	/* adding space to not brake next command in the buffer */
	completion_addr[cmd_len] = ' ';

	*buff_len += cmd_len + 1; /* + 1 for space */

	return SHELL_WILDCARD_CMD_ADDED;
}

/**
 * @internal @brief Function for searching and adding commands to the temporary
 * shell buffer matching to wildcard pattern.
 *
 * Function will search commands tree for commands matching wildcard pattern
 * stored in argv[cmd_lvl]. When match is found wildcard pattern will be
 * replaced by matching commands. If there is no space in the buffer to add all
 * matching commands function will add as many as possible. Next it will
 * continue to search for next wildcard pattern and it will try to add matching
 * commands.
 *
 *
 * This function is internal to shell module and shall be not called directly.
 *
 * @param[in/out] shell		Pointer to the CLI instance.
 * @param[in]	  cmd		Pointer to command which will be processed
 * @param[in]	  pattern	Pointer to wildcard pattern.
 *
 * @retval WILDCARD_CMD_ADDED	All matching commands added to the buffer.
 * @retval WILDCARD_CMD_ADDED_MISSING_SPACE  Not all matching commands added
 *					     because CONFIG_SHELL_CMD_BUFF_SIZE
 *					     is too small.
 * @retval WILDCARD_CMD_NO_MATCH_FOUND No matching command found.
 */
static enum shell_wildcard_status commands_expand(const struct shell *shell,
					      const struct shell_cmd_entry *cmd,
					      const char *pattern)
{
	enum shell_wildcard_status ret_val = SHELL_WILDCARD_CMD_NO_MATCH_FOUND;
	struct shell_static_entry const *p_static_entry = NULL;
	struct shell_static_entry static_entry;
	size_t cmd_idx = 0;
	size_t cnt = 0;

	do {
		subcmd_get(cmd, cmd_idx++, &p_static_entry, &static_entry);

		if (!p_static_entry) {
			break;
		}

		if (fnmatch(pattern, p_static_entry->syntax, 0) == 0) {
			ret_val = command_add(shell->ctx->temp_buff,
					      &shell->ctx->cmd_tmp_buff_len,
					      p_static_entry->syntax, pattern);
			if (ret_val == SHELL_WILDCARD_CMD_MISSING_SPACE) {
				shell_fprintf(shell,
					      SHELL_WARNING,
					      "Command buffer is too short to"
					      " expand all commands matching"
					      " wildcard pattern: %s\n",
					      pattern);
				break;
			} else if (ret_val != SHELL_WILDCARD_CMD_ADDED) {
				break;
			}
			cnt++;
		}
	} while (cmd_idx);

	if (cnt > 0) {
		shell_pattern_remove(shell->ctx->temp_buff,
				     &shell->ctx->cmd_tmp_buff_len, pattern);
	}

	return ret_val;
}

bool shell_wildcard_character_exist(const char *str)
{
	u16_t str_len = shell_strlen(str);

	for (size_t i = 0; i < str_len; i++) {
		if ((str[i] == '?') || (str[i] == '*')) {
			return true;
		}
	}

	return false;
}

void shell_wildcard_prepare(const struct shell *shell)
{
	/* Wildcard can be correctly handled under following conditions:
	 * - wildcard command does not have a handler
	 * - wildcard command is on the deepest commands level
	 * - other commands on the same level as wildcard command shall also not
	 *   have a handler
	 *
	 * Algorithm:
	 * 1. Command buffer: ctx->cmd_buff is copied to temporary buffer:
	 *    ctx->temp_buff.
	 * 2. Algorithm goes through command buffer to find handlers and
	 *    subcommands.
	 * 3. If algorithm will find a wildcard character it switches to
	 *    Temporary buffer.
	 * 4. In the Temporary buffer command containing wildcard character is
	 *    replaced by matching command(s).
	 * 5. Algorithm switch back to Command buffer and analyzes next command.
	 * 6. When all arguments are analyzed from Command buffer, Temporary
	 *    buffer with all expanded commands is copied to Command buffer.
	 * 7. Deepest found handler is executed and all lower level commands,
	 *    including expanded commands, are passed as arguments.
	 */

	memset(shell->ctx->temp_buff, 0, sizeof(shell->ctx->temp_buff));
	memcpy(shell->ctx->temp_buff,
			shell->ctx->cmd_buff,
			shell->ctx->cmd_buff_len);

	/* Function shell_spaces_trim must be used instead of shell_make_argv.
	 * At this point it is important to keep temp_buff as one string.
	 * It will allow to find wildcard commands easily with strstr function.
	 */
	shell_spaces_trim(shell->ctx->temp_buff);

	/* +1 for EOS*/
	shell->ctx->cmd_tmp_buff_len = shell_strlen(shell->ctx->temp_buff) + 1;
}


enum shell_wildcard_status shell_wildcard_process(const struct shell *shell,
					      const struct shell_cmd_entry *cmd,
					      const char *pattern)
{
	enum shell_wildcard_status ret_val = SHELL_WILDCARD_NOT_FOUND;

	if (cmd == NULL) {
		return ret_val;
	}

	if (!shell_wildcard_character_exist(pattern)) {
		return ret_val;
	}

	/* Function will search commands tree for commands matching wildcard
	 * pattern stored in argv[cmd_lvl]. When match is found wildcard pattern
	 * will be replaced by matching commands. If there is no space in the
	 * buffer to add all matching commands function will add as many as
	 * possible. Next it will continue to search for next wildcard pattern
	 * and it will try to add matching commands.
	 */
	ret_val = commands_expand(shell, cmd, pattern);

	return ret_val;
}

void shell_wildcard_finalize(const struct shell *shell)
{
	memcpy(shell->ctx->cmd_buff,
	       shell->ctx->temp_buff,
	       shell->ctx->cmd_tmp_buff_len);
	shell->ctx->cmd_buff_len = shell->ctx->cmd_tmp_buff_len;
}
