1package gui
2
3import (
4	"context"
5
6	"github.com/mum4k/termdash/container"
7	"github.com/mum4k/termdash/keyboard"
8	"github.com/mum4k/termdash/terminal/terminalapi"
9
10	"github.com/nakabonne/ali/attacker"
11)
12
13func navigateCharts(chartFuncs []func()) func(bool) {
14	position := 0
15	numFuncs := len(chartFuncs)
16	return func(backwards bool) {
17		position++
18		if backwards {
19			position -= 2
20			if position < 0 {
21				position = numFuncs - 1
22			}
23		}
24		chartFuncs[position%numFuncs]()
25	}
26}
27
28func keybinds(ctx context.Context, cancel context.CancelFunc, c *container.Container, dr *drawer, a attacker.Attacker) func(*terminalapi.Keyboard) {
29	funcs := []func(){
30		func() { c.Update(chartID, dr.gridOpts.latency...) },
31		func() { c.Update(chartID, dr.gridOpts.percentiles...) },
32	}
33	navigateFunc := navigateCharts(funcs)
34	return func(k *terminalapi.Keyboard) {
35		switch k.Key {
36		case keyboard.KeyCtrlC, 'q': // Quit
37			cancel()
38		case keyboard.KeyEnter: // Attack
39			attack(ctx, dr, a)
40		case 'H', 'h': // backwards
41			navigateFunc(true)
42		case 'L', 'l': // forwards
43			navigateFunc(false)
44		}
45	}
46}
47
48func attack(ctx context.Context, d *drawer, a attacker.Attacker) {
49	if d.chartDrawing.Load() {
50		return
51	}
52	child, cancel := context.WithCancel(ctx)
53
54	// To initialize, run redrawChart on a per-attack basis.
55	go d.redrawCharts(child)
56	go d.redrawGauge(child, a.Duration())
57	go func() {
58		a.Attack(child, d.metricsCh) // this blocks until attack finishes
59		cancel()
60	}()
61}
62