/*
 * Copyright (c) 2015 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file
 * @brief Console handler implementation of shell.h API
 */


#include <zephyr.h>
#include <stdio.h>
#include <string.h>

#include <console/uart_console.h>
#include <misc/printk.h>
#include <misc/util.h>

#include <misc/shell.h>

/* maximum number of command parameters */
#define ARGC_MAX 10

static const struct shell_cmd *commands;

static const char *prompt;

#define STACKSIZE CONFIG_CONSOLE_HANDLER_SHELL_STACKSIZE
static char __stack stack[STACKSIZE];

#define MAX_CMD_QUEUED 3
static struct uart_console_input buf[MAX_CMD_QUEUED];

static struct nano_fifo avail_queue;
static struct nano_fifo cmds_queue;

static shell_cmd_function_t app_cmd_handler;
static shell_prompt_function_t app_prompt_handler;

static const char *get_prompt(void)
{
	if (app_prompt_handler) {
		const char *str;

		str = app_prompt_handler();
		if (str) {
			return str;
		}
	}

	return prompt;
}

static void line_queue_init(void)
{
	int i;

	for (i = 0; i < MAX_CMD_QUEUED; i++) {
		nano_fifo_put(&avail_queue, &buf[i]);
	}
}

static size_t line2argv(char *str, char *argv[], size_t size)
{
	size_t argc = 0;

	if (!strlen(str)) {
		return 0;
	}

	while (*str && *str == ' ') {
		str++;
	}

	if (!*str) {
		return 0;
	}

	argv[argc++] = str;

	while ((str = strchr(str, ' '))) {
		*str++ = '\0';

		while (*str && *str == ' ') {
			str++;
		}

		if (!*str) {
			break;
		}

		argv[argc++] = str;

		if (argc == size) {
			printk("Too many parameters (max %u)\n", size - 1);
			return 0;
		}
	}

	/* keep it POSIX style where argv[argc] is required to be NULL */
	argv[argc] = NULL;

	return argc;
}

static int show_cmd_help(int argc, char *argv[])
{
	int i;

	if (!argv[0] || argv[0][0] == '\0') {
		goto done;
	}

	for (i = 0; commands[i].cmd_name; i++) {
		if (!strcmp(argv[0], commands[i].cmd_name)) {
			printk("%s %s\n", commands[i].cmd_name,
			       commands[i].help ? commands[i].help : "");
			return 0;
		}
	}

done:
	printk("Unrecognized command: %s\n", argv[0]);
	return 0;
}

static int show_help(int argc, char *argv[])
{
	int i;

	if (argc > 1) {
		return show_cmd_help(--argc, &argv[1]);
	}

	printk("Available commands:\n");
	printk("help\n");

	for (i = 0; commands[i].cmd_name; i++) {
		printk("%s\n", commands[i].cmd_name);
	}

	return 0;
}

static shell_cmd_function_t get_cb(const char *string)
{
	int i;

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

	if (!strcmp(string, "help")) {
		return show_help;
	}

	for (i = 0; commands[i].cmd_name; i++) {
		if (!strcmp(string, commands[i].cmd_name)) {
			return commands[i].cb;
		}
	}

	return NULL;
}

static void shell(int arg1, int arg2)
{
	char *argv[ARGC_MAX + 1];
	size_t argc;

	while (1) {
		struct uart_console_input *cmd;
		shell_cmd_function_t cb;

		printk("%s", get_prompt());

		cmd = nano_fiber_fifo_get(&cmds_queue, TICKS_UNLIMITED);

		argc = line2argv(cmd->line, argv, ARRAY_SIZE(argv));
		if (!argc) {
			nano_fiber_fifo_put(&avail_queue, cmd);
			continue;
		}

		cb = get_cb(argv[0]);
		if (!cb) {
			if (app_cmd_handler != NULL) {
				cb = app_cmd_handler;
			} else {
				printk("Unrecognized command: %s\n", argv[0]);
				printk("Type 'help' for list of available commands\n");
				nano_fiber_fifo_put(&avail_queue, cmd);
				continue;
			}
		}

		/* Execute callback with arguments */
		if (cb(argc, argv) < 0) {
			show_cmd_help(argc, argv);
		}

		nano_fiber_fifo_put(&avail_queue, cmd);
	}
}

static uint8_t completion(char *line, uint8_t len)
{
	char cmds[MAX_LINE_LEN];
	int common_chars = -1;
	size_t cmds_len = 0;
	int i;

	for (i = 0; commands[i].cmd_name; i++) {
		int name_len, j;

		if (strncmp(line, commands[i].cmd_name, len)) {
			continue;
		}

		name_len = strlen(commands[i].cmd_name);
		if (name_len > (MAX_LINE_LEN - (cmds_len + 1))) {
			break;
		}

		memcpy(cmds + cmds_len, commands[i].cmd_name, name_len);
		cmds_len += name_len;
		cmds[cmds_len++] = '\n';

		/* first match */
		if (common_chars < 0) {
			common_chars = name_len;
			continue;
		}

		/* cut common part of matching names */
		for (j = 0; j < common_chars; j++) {
			if (cmds[j] != commands[i].cmd_name[j]) {
				break;
			}
		}

		common_chars = j;
	}

	/* no match */
	if (common_chars < 0) {
		return 0;
	}

	/* alter line with common part of commands */
	memcpy(line + len, cmds + len, common_chars - len);

	if (common_chars < cmds_len - 1) {
		/*
		 * more than one match, print matching commands, restore prompt
		 * and print common part of matched commands
		 */
		cmds[cmds_len] = '\0';
		printk("\n%s", cmds);

		/* restore prompt */
		printk("%s", get_prompt());

		/* print common part after prompt */
		for (i = 0; i < common_chars; i++) {
			printk("%c", line[i]);
		}
	} else {
		/* only one match, complete command name */
		for (i = len; i < common_chars; i++) {
			printk("%c", line[i]);
		}

		/* for convenience add space after command */
		printk(" ");
		line[common_chars] = ' ';
		common_chars++;
	}

	return common_chars - len;
}

void shell_init(const char *str, const struct shell_cmd *cmds)
{
	nano_fifo_init(&cmds_queue);
	nano_fifo_init(&avail_queue);

	commands = cmds;

	line_queue_init();

	prompt = str ? str : "";

	task_fiber_start(stack, STACKSIZE, shell, 0, 0, 7, 0);

	/* Register serial console handler */
	uart_register_input(&avail_queue, &cmds_queue, completion);
}

/** @brief Optionally register an app default cmd handler.
 *
 *  @param handler To be called if no cmd found in cmds registered with shell_init.
 */
void shell_register_app_cmd_handler(shell_cmd_function_t handler)
{
	app_cmd_handler = handler;
}

void shell_register_prompt_handler(shell_prompt_function_t handler)
{
	app_prompt_handler = handler;
}
