View Javadoc
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 }