import os
import time
import flag

struct Context {
mut:
	show_help bool
	timeout   time.Duration
	delay     time.Duration
	retries   int
}

fn main() {
	mut context := Context{}
	args := os.args#[1..]
	// dump(args)
	mut fp := flag.new_flag_parser(args)
	fp.application('v retry')
	fp.version('0.0.1')
	fp.description('Run the command CMD in a loop, until it succeeds, or until a predetermined amount of seconds pass.')
	fp.arguments_description('CMD')
	fp.skip_executable()
	fp.limit_free_args_to_at_least(1)!
	context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
	context.timeout = fp.float('timeout', `t`, 900.0, 'Timeout in seconds (for all retries). Default: 900.0 seconds (15 minutes).') * time.second
	context.delay = fp.float('delay', `d`, 1.0, 'Delay between each retry in seconds. Default: 1.0 second.') * time.second
	context.retries = fp.int('retries', `r`, 10, 'Maximum number of retries. Default: 10.')
	if context.show_help {
		println(fp.usage())
		exit(0)
	}
	command_args := fp.finalize() or {
		eprintln('error: ${err}')
		exit(1)
	}
	cmd := command_args.join(' ')
	// dump(cmd)

	spawn fn (context Context) {
		time.sleep(context.timeout)
		eprintln('error: exceeded maximum timeout (${context.timeout.seconds()}s)!')
		exit(1)
	}(context)

	mut res := 0
	for i in 0 .. context.retries {
		res = os.system(cmd)
		if res == 0 {
			break
		}
		if i == context.retries - 1 {
			eprintln('error: exceeded maximum number of retries (${context.retries})!')
			exit(res)
		}
		time.sleep(context.delay)
	}
	exit(res)
}
