1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use sysinfo::{System, SystemExt, CpuExt};
use tui::{
    backend::{Backend, CrosstermBackend},
    widgets::{Block, Borders, Paragraph},
    layout::{Constraint, Direction, Layout},
    style::{Style, Color},
    text::{Spans, Span},
    Terminal,
};
use crossterm::{
    event::{self, Event, KeyCode},
    execute,
    terminal::{EnterAlternateScreen, LeaveAlternateScreen},
};
use std::{io, time::{Duration, Instant}};

pub struct SystemInfo {
    pub total_memory: u64,
    pub used_memory: u64,
    pub cpu_usage: Vec<f32>,
}

pub fn get_system_info() -> SystemInfo {
    let mut sys = System::new_all();
    sys.refresh_all();

    let total_memory = sys.total_memory();
    let used_memory = sys.used_memory();
    
    // Using `cpus()` to get CPU usage
    let cpu_usage = sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect();

    SystemInfo {
        total_memory,
        used_memory,
        cpu_usage,
    }
}

pub fn start_tui<B: Backend>(terminal: &mut Terminal<B>, system_info: &SystemInfo) -> io::Result<()> {
    terminal.draw(|f| {
        let size = f.size();

        // Create layout
        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .margin(1)
            .constraints(
                [
                    Constraint::Percentage(50),
                    Constraint::Percentage(50),
                ].as_ref(),
            )
            .split(size);

        // Display memory usage
        let memory_block = Block::default()
            .title("Memory Usage")
            .borders(Borders::ALL);
        let memory_usage = Paragraph::new(format!(
            "Total Memory: {} MB\nUsed Memory: {} MB",
            system_info.total_memory / 1024,
            system_info.used_memory / 1024
        ))
        .block(memory_block)
        .style(Style::default().fg(Color::White));
        f.render_widget(memory_usage, chunks[0]);

        // Display CPU usage
        let cpu_block = Block::default()
            .title("CPU Usage")
            .borders(Borders::ALL);
        let cpu_usage_text = system_info.cpu_usage.iter()
            .enumerate()
            .map(|(i, usage)| Spans::from(Span::raw(format!("CPU {}: {:.2}%", i, usage))))
            .collect::<Vec<Spans>>();
        let cpu_usage = Paragraph::new(cpu_usage_text)
            .block(cpu_block)
            .style(Style::default().fg(Color::White));
        f.render_widget(cpu_usage, chunks[1]);
    })?;

    Ok(())
}

pub fn run() -> Result<(), io::Error> {
    // Setup terminal
    crossterm::terminal::enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    // Initialize system information
    let system_info = get_system_info();

    // Run TUI loop
    let tick_rate = Duration::from_millis(1000);
    let mut last_tick = Instant::now();
    loop {
        start_tui(&mut terminal, &system_info)?;

        if event::poll(tick_rate - last_tick.elapsed())? {
            if let Event::Key(key) = event::read()? {
                if key.code == KeyCode::Char('q') {
                    break;
                }
            }
        }

        if last_tick.elapsed() >= tick_rate {
            last_tick = Instant::now();
        }
    }

    // Cleanup terminal
    execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
    crossterm::terminal::disable_raw_mode()?;

    Ok(())
}