1 package com.guinetik.hexafun.examples.sysmon;
2
3 import static com.guinetik.hexafun.examples.sysmon.SysmonKeys.*;
4 import static com.guinetik.hexafun.examples.tui.Ansi.*;
5
6 import com.guinetik.hexafun.HexaApp;
7 import com.guinetik.hexafun.examples.tui.HexaTerminal;
8
9 /**
10 * Immutable state for the System Monitor TUI.
11 *
12 * <p>This record holds all state needed to render the UI and process
13 * user input. State transitions produce new instances rather than
14 * mutating, enabling a functional TUI pattern.</p>
15 *
16 * <h2>State Transitions</h2>
17 * <ul>
18 * <li>{@link #withFormat(SysmonFormat)} - Switch output format</li>
19 * <li>{@link #withStatus(String, String)} - Show status message</li>
20 * <li>{@link #refresh()} - Recalculate metrics</li>
21 * <li>{@link #stop()} - Signal exit</li>
22 * </ul>
23 *
24 * @param app The HexaApp instance for invoking use cases and adapters
25 * @param format Current output format selection
26 * @param width Terminal width for responsive layout
27 * @param status Status message to display
28 * @param statusColor ANSI color for status message
29 * @param running Whether the TUI should continue running
30 */
31 public record SysmonState(
32 HexaApp app,
33 SysmonFormat format,
34 int width,
35 String status,
36 String statusColor,
37 boolean running
38 ) {
39 private static final int MIN_WIDTH = 50;
40
41 /**
42 * Create initial state with default values.
43 *
44 * @param app The configured HexaApp instance
45 * @return Initial state ready for rendering
46 */
47 public static SysmonState initial(HexaApp app) {
48 return new SysmonState(app, SysmonFormat.TUI, detectWidth(), "", GREEN, true);
49 }
50
51 /**
52 * Transition to a new output format.
53 *
54 * @param f The new format to use
55 * @return New state with format changed and status message
56 */
57 public SysmonState withFormat(SysmonFormat f) {
58 return new SysmonState(
59 app,
60 f,
61 width,
62 "Switched to " + f.label,
63 f.color,
64 running
65 );
66 }
67
68 /**
69 * Set a status message.
70 *
71 * @param msg The message to display
72 * @param color ANSI color for the message
73 * @return New state with status updated
74 */
75 public SysmonState withStatus(String msg, String color) {
76 return new SysmonState(app, format, width, msg, color, running);
77 }
78
79 /**
80 * Signal that the TUI should stop.
81 *
82 * @return New state with running=false
83 */
84 public SysmonState stop() {
85 return new SysmonState(app, format, width, "Goodbye!", CYAN, false);
86 }
87
88 /**
89 * Refresh state, re-detecting terminal width.
90 *
91 * @return New state with cleared status and updated width
92 */
93 public SysmonState refresh() {
94 return new SysmonState(app, format, detectWidth(), "", GREEN, running);
95 }
96
97 /**
98 * Get current system metrics by invoking the GET_ALL use case.
99 *
100 * @return Current SystemMetrics from the provider
101 */
102 public SystemMetrics metrics() {
103 return app.invoke(GET_ALL, null);
104 }
105
106 private static int detectWidth() {
107 return HexaTerminal.detectWidth(MIN_WIDTH, 80);
108 }
109 }