/*
 * Copyright (c) 2016-2021 Satlab A/S <satlab@satlab.com>
 * All rights reserved. Do not distribute without permission.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#include <util/colorprint.h>
#include <slash/slash.h>

static int cmd_watch(struct slash *slash)
{
	int i, c, ret = 0;
	int total = 0, good = 0, bad = 0;
	char command[100] = "", command_exec[100];
	bool stop_error = false, show_stats = false, blank = false;
	bool header_shown = false;
	unsigned int sleep = 1000, count = UINT_MAX;

	while ((c = slash_getopt(slash, "c:n:esb")) != -1) {
		switch (c) {
		case 'b':
			blank = true;
			break;
		case 'e':
			stop_error = true;
			break;
		case 's':
			show_stats = true;
			break;
		case 'n':
			sleep = atoi(slash->optarg);
			break;
		case 'c':
			count = atoi(slash->optarg);
			break;
		default:
			return SLASH_EUSAGE;

		}
	}

	if (slash->argc - slash->optind < 1)
		return SLASH_EUSAGE;

	/* slash_execute currently mangles the command so make a copy */
	for (i = slash->optind; i < slash->argc; i++) {
		strncat(command, slash->argv[i], sizeof(command) - 1);
		if (i != slash->argc - 1)
			strncat(command, " ", sizeof(command) - 1);
		command[sizeof(command) - 1] = '\0';
	}

	while (count--) {
		/* Update command */
		strncpy(command_exec, command, sizeof(command) - 1);
		command_exec[sizeof(command) - 1] = '\0';

		/* Blank screen */
		if (blank)
			slash_clear_screen(slash);

		if (blank || !header_shown) {
			cprintf(COLOR_WHITE, "Running command '%s' every %u ms\n",
				command_exec, sleep);
			header_shown = true;
		}

		/* Run command, exit if not found */
		ret = slash_execute(slash, command_exec);
		if (ret == -ENOENT || ret == -EINVAL || ret == SLASH_EUSAGE)
			return SLASH_EINVAL;

		/* Stats bookkeeping */
		total++;
		if (ret) {
			bad++;
			if (stop_error)
				break;
		} else {
			good++;
		}
		ret = 0;

		/* Wait interruptible */
		if (count) {
			ret = slash_wait_interruptible(slash, sleep);
			if (ret > 0) {
				ret = 0;
				cprintf(COLOR_WHITE, "Interrupted\n");
				break;
			}
		}
	}

	if (show_stats) {
		cprintf(COLOR_WHITE, "%d executions, %d success %d failures\n",
		        total, good, bad);
	}

	return ret;
}
slash_command(watch, cmd_watch, "[-es] [-n ms] [-c count] <command>",
	      "Run command periodically");
