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

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "nsi_cmdline.h"
#include "nsi_cmdline_internal.h"
#include "nsi_tracing.h"
#include "nsi_timer_model.h"
#include "nsi_hw_scheduler.h"
#include "nsi_tasks.h"

static int s_argc, test_argc;
static char **s_argv, **test_argv;

/* Extra "command line options" provided programmatically: */
static int extra_argc;
static char **extra_argv;

static struct args_struct_t *args_struct;
static int used_args;
static int args_aval;
#define ARGS_ALLOC_CHUNK_SIZE 20

static void nsi_cleanup_cmd_line(void)
{
	if (args_struct != NULL) { /* LCOV_EXCL_BR_LINE */
		free(args_struct);
		args_struct = NULL;
	}
}

NSI_TASK(nsi_cleanup_cmd_line, ON_EXIT_POST, 0);

/**
 * Add a set of command line options to the program.
 *
 * Each option to be added is described in one entry of the input <args>
 * This input must be terminated with an entry containing ARG_TABLE_ENDMARKER.
 */
void nsi_add_command_line_opts(struct args_struct_t *args)
{
	int count = 0;

	while (args[count].option != NULL) {
		count++;
	}
	count++; /*for the end marker*/

	if (used_args + count >= args_aval) {
		int growby = count;
		/* reallocs are expensive let's do them only in big chunks */
		if (growby < ARGS_ALLOC_CHUNK_SIZE) {
			growby = ARGS_ALLOC_CHUNK_SIZE;
		}

		struct args_struct_t *new_args_struct = realloc(args_struct,
				      (args_aval + growby)*
				      sizeof(struct args_struct_t));
		args_aval += growby;
		/* LCOV_EXCL_START */
		if (new_args_struct == NULL) {
			nsi_print_error_and_exit("Could not allocate memory");
		} else {
			args_struct = new_args_struct;
		}
		/* LCOV_EXCL_STOP */
	}

	memcpy(&args_struct[used_args], args,
		count*sizeof(struct args_struct_t));

	used_args += count - 1;
	/*
	 * -1 as the end marker should be overwritten next time something
	 * is added
	 */
}

void nsi_add_testargs_option(void)
{
	static struct args_struct_t testargs_options[] = {
		{
		.manual = true,
		.option = "testargs",
		.name = "arg",
		.type = 'l',
		.descript = "Any argument that follows will be ignored by the top level, "
			    "and made available for possible tests"
		},
		ARG_TABLE_ENDMARKER
	};

	nsi_add_command_line_opts(testargs_options);
}

static void print_invalid_opt_error(char *argv)
{
	nsi_print_error_and_exit("Incorrect option '%s'. Did you misspell it?"
				 " Is that feature supported in this build?\n",
				 argv);

}

/**
 * Handle possible command line arguments.
 *
 * We also store them for later use by possible test applications
 */
void nsi_handle_cmd_line(int argc, char *argv[])
{
	int i;

	nsi_add_testargs_option();

	s_argv = argv;
	s_argc = argc;

	nsi_cmd_args_set_defaults(args_struct);

	for (int i = 0; i < extra_argc; i++) {
		if (!nsi_cmd_parse_one_arg(extra_argv[i], args_struct)) {
			nsi_cmd_print_switches_help(args_struct);
			print_invalid_opt_error(extra_argv[i]);
		}
	}

	for (i = 1; i < argc; i++) {

		if ((nsi_cmd_is_option(argv[i], "testargs", 0))) {
			test_argc = argc - i - 1;
			test_argv = &argv[i+1];
			break;
		}

		if (!nsi_cmd_parse_one_arg(argv[i], args_struct)) {
			nsi_cmd_print_switches_help(args_struct);
			print_invalid_opt_error(argv[i]);
		}
	}
}

void nsi_register_extra_args(int argc, char *argv[])
{
	int new_size = extra_argc + argc;

	extra_argv = realloc(extra_argv, new_size*sizeof(char *));
	for (int i = 0; i < argc; i++) {
		memcpy(&extra_argv[extra_argc], argv, argc*sizeof(char *));
	}
	extra_argc += argc;
}

static void clear_extra_args(void)
{
	free(extra_argv);
}

NSI_TASK(clear_extra_args, ON_EXIT_PRE, 100);

/**
 * The application/test can use this function to inspect all the command line
 * arguments
 */
void nsi_get_cmd_line_args(int *argc, char ***argv)
{
	*argc = s_argc;
	*argv = s_argv;
}

/**
 * The application/test can use this function to inspect the command line
 * arguments received after --testargs
 */
void nsi_get_test_cmd_line_args(int *argc, char ***argv)
{
	*argc = test_argc;
	*argv = test_argv;
}
