# TUI Integration Guide

Complete guide for integrating RataTui-based TUI into any Tools ecosystem project.

## Overview

The `tools-tui-shared` library provides a production-ready foundation for building terminal user interfaces (TUIs) across the Tools ecosystem. All TUI implementations follow strict architectural patterns and code quality standards.

## Quick Start: 5 Steps

### Step 1: Add Dependency

```toml
[dependencies]
tools-tui-shared = { path = "../../../shared/rust-tui" }
ratatui = { version = "0.30.0-beta.0", features = ["all-widgets"] }
crossterm = "0.29"
tui-textarea = "0.7"
```

### Step 2: Create App State

```rust
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ScreenType {
    List,
    Detail,
}

#[derive(Clone, Debug)]
pub struct AppState {
    pub current_screen: ScreenType,
    pub items: Vec<YourType>,
    pub selected_index: usize,
    pub dirty: bool,
    pub should_quit: bool,
}

impl AppState {
    pub fn new() -> Self {
        AppState {
            current_screen: ScreenType::List,
            items: Vec::new(),
            selected_index: 0,
            dirty: true,
            should_quit: false,
        }
    }
}
```

### Step 3: Implement Screens

```rust
use crate::app::AppState;
use tools_tui_shared::prelude::*;
use ratatui::prelude::*;
use ratatui::widgets::{Block, Borders, List, ListItem};

pub struct ListScreen;

impl ListScreen {
    pub fn render(state: &AppState, frame: &mut ratatui::Frame, area: Rect) {
        let theme = Theme::dark();

        let items: Vec<ListItem> = state.items.iter()
            .enumerate()
            .map(|(idx, item)| {
                let marker = if idx == state.selected_index { "★ " } else { "  " };
                ListItem::new(format!("{}{}", marker, item.name))
            })
            .collect();

        let list = List::new(items)
            .block(Block::default()
                .title("Items")
                .borders(Borders::ALL)
                .border_style(theme.focused_style()))
            .style(theme.normal_style());

        frame.render_widget(list, area);
    }
}
```

### Step 4: Create lib.rs

```rust
#![forbid(unsafe_code)]
#![warn(missing_docs)]

pub mod app;
pub mod screens;

pub use app::{AppState, ScreenType};

pub mod prelude {
    pub use crate::{AppState, ScreenType};
    pub use crate::screens::{ListScreen, DetailScreen};
}
```

### Step 5: Run Tests

```bash
cargo test --lib
```

## Architecture Patterns

### R-STATE-SEPARATION

**Principle**: Complete separation of state from rendering logic.

```rust
// ✅ CORRECT: State methods don't render
impl AppState {
    pub fn select_next(&mut self) {
        if !self.items.is_empty() {
            self.selected_index = (self.selected_index + 1) % self.items.len();
            self.dirty = true;
        }
    }
}

// ✅ CORRECT: Render methods only read state
impl ListScreen {
    pub fn render(state: &AppState, frame: &mut ratatui::Frame, area: Rect) {
        // Never call state.select_next() or other mutation methods
        // Only read: state.selected_index, state.items, etc.
    }
}

// ❌ WRONG: Don't put rendering logic in state
impl AppState {
    pub fn render(&self) { } // DON'T DO THIS
}
```

### R-WIDGET-COMPOSITION

**Principle**: Build complex UIs from simple, reusable widgets.

```rust
// Use shared widgets from tools-tui-shared
use tools_tui_shared::widgets::{Menu, Form, Table, StatusBar};

// Compose widgets for your screens
let menu = Menu::new(vec![
    MenuItem::new("Save".to_string()).with_key_binding("Ctrl+S"),
    MenuItem::new("Exit".to_string()).with_key_binding("Ctrl+Q"),
]);

let form = Form::new()
    .add_field(FormField::new("name", FieldType::Text))
    .add_field(FormField::new("email", FieldType::Text));
```

### R-CONSISTENT-THEMING

**Principle**: Single theme source for all colors and styles.

```rust
let theme = Theme::dark();

// All UI elements use the same theme
let primary_style = theme.selected_style();    // Header, emphasis
let success_style = theme.success_style();      // Success messages
let warning_style = theme.warning_style();      // Warnings
let error_style = theme.error_style();          // Errors
let normal_style = theme.normal_style();        // Default text
let dimmed_style = theme.dimmed_style();        // Disabled/background
```

### R-EVENT-LOOP

**Principle**: Non-blocking event polling with timeout.

```rust
use tools_tui_shared::events::EventHandler;

let event_handler = EventHandler::new(100)?; // 100ms tick rate

loop {
    if app_state.dirty {
        terminal.draw(|f| render(f, &app_state))?;
        app_state.reset_dirty();
    }

    // Non-blocking poll with timeout
    match event_handler.poll()? {
        AppEvent::Tick => { /* Update */},
        AppEvent::Key(key) => { /* Handle key */},
        AppEvent::Mouse(evt) => { /* Handle mouse */},
        AppEvent::Resize(w, h) => { /* Handle resize */},
    }
}
```

### R-GRACEFUL-SHUTDOWN

**Principle**: RAII pattern ensures terminal cleanup on exit.

```rust
use tools_tui_shared::terminal::TerminalGuard;

// Terminal is automatically set up and cleaned up
let _guard = TerminalGuard::setup()?;
let mut terminal = _guard.terminal()?;

// Even if panic occurs, terminal is restored
// Drop trait automatically handles cleanup
```

## Common Patterns

### Dirty Flag Optimization

Only redraw when state changes:

```rust
pub fn is_dirty(&self) -> bool {
    self.dirty
}

pub fn reset_dirty(&mut self) {
    self.dirty = false;
}

pub fn mark_dirty(&mut self) {
    self.dirty = true;
}

// In main event loop:
if app_state.is_dirty() {
    terminal.draw(|f| render(f, &app_state))?;
    app_state.reset_dirty();
}
```

### Selection Navigation

Implement consistent navigation:

```rust
pub fn select_next(&mut self) {
    if !self.items.is_empty() {
        self.selected_index = (self.selected_index + 1) % self.items.len();
        self.dirty = true;
    }
}

pub fn select_previous(&mut self) {
    if !self.items.is_empty() {
        self.selected_index = if self.selected_index == 0 {
            self.items.len() - 1
        } else {
            self.selected_index - 1
        };
        self.dirty = true;
    }
}
```

### Screen Navigation

Manage multiple screens:

```rust
pub fn set_screen(&mut self, screen: ScreenType) {
    if self.current_screen != screen {
        self.current_screen = screen;
        self.dirty = true;
    }
}

// In render loop:
match state.current_screen {
    ScreenType::List => ListScreen::render(state, frame, area),
    ScreenType::Detail => DetailScreen::render(state, frame, area),
}
```

## Testing Guidelines

Each module should have comprehensive tests:

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_app_state_new() {
        let state = AppState::new();
        assert!(state.dirty);
        assert!(!state.should_quit);
    }

    #[test]
    fn test_select_next() {
        let mut state = AppState::new();
        state.items.push(/* ... */);
        state.select_next();
        assert_eq!(state.selected_index, 1);
    }

    #[test]
    fn test_screen_navigation() {
        let mut state = AppState::new();
        state.set_screen(ScreenType::Detail);
        assert_eq!(state.current_screen, ScreenType::Detail);
    }
}
```

**Minimum test coverage**: 15+ tests per module

## Code Quality Checklist

- [ ] `#![forbid(unsafe_code)]` at crate root
- [ ] `#![warn(missing_docs)]` for public items
- [ ] All public types implement Debug
- [ ] All public functions documented with examples
- [ ] Result<T> for all fallible operations
- [ ] No unwrap() in production code
- [ ] 15+ tests per module
- [ ] cargo fmt applied
- [ ] cargo clippy passes
- [ ] cargo test --workspace passes

## Integration with Dashboard

To register your tool in the multi-tool dashboard:

```rust
use tools_tui_shared::integration::ToolSummaryProvider;

pub struct MyToolTui;

impl ToolSummaryProvider for MyToolTui {
    fn name(&self) -> &str {
        "my-tool"
    }

    fn summary(&self) -> Result<ToolSummary, String> {
        Ok(ToolSummary::new(
            "my-tool".to_string(),
            "My Tool".to_string(),
            "Description of my tool".to_string(),
            ToolMetrics::new(10, 5, 3, chrono::Utc::now().to_rfc2822()),
        ).with_commands(vec!["list".to_string(), "create".to_string()]))
    }

    fn execute_command(&self, command: &str, _args: &[String]) -> Result<String, String> {
        match command {
            "list" => Ok("Listing items...".to_string()),
            "create" => Ok("Creating item...".to_string()),
            _ => Err(format!("Unknown command: {}", command)),
        }
    }
}
```

## Common Issues & Solutions

### Issue: Compilation errors with ratatui widgets

**Solution**: Ensure you're using ratatui 0.30.0-beta.0 or later:

```toml
ratatui = { version = "0.30.0-beta.0", features = ["all-widgets", "underline-color"] }
```

### Issue: Terminal not being cleaned up properly

**Solution**: Use TerminalGuard:

```rust
use tools_tui_shared::terminal::TerminalGuard;

let _guard = TerminalGuard::setup()?;
let mut terminal = _guard.terminal()?;
// Terminal is auto-cleaned up when _guard is dropped
```

### Issue: UI not updating

**Solution**: Check dirty flag logic:

```rust
// Always mark dirty when state changes
pub fn some_action(&mut self) {
    self.items.push(new_item);
    self.dirty = true;  // Don't forget this!
}

// Always reset dirty after rendering
if app_state.is_dirty() {
    terminal.draw(|f| render(f, &app_state))?;
    app_state.reset_dirty();  // Don't forget this!
}
```

## Performance Tips

1. **Use dirty flag** to avoid unnecessary redraws
2. **Limit event polling** with reasonable tick rates (100-200ms)
3. **Cache theme** instead of creating new Theme each render
4. **Use Constraint::Percentage** for responsive layouts instead of hardcoded sizes
5. **Avoid cloning** large data structures in render methods

## References

- **RataTui Documentation**: https://ratatui.rs
- **Crossterm Documentation**: https://docs.rs/crossterm
- **Tools Shared Library**: `/Users/Akasha/Tools/shared/rust-tui/`
- **Example Implementation**: `/Users/Akasha/Tools/hello-tool/crates/hello-tui/`

## Getting Help

1. Check existing tool implementations in `/Users/Akasha/Tools/*/crates/*-tui/`
2. Review `tools-tui-shared` source code for patterns
3. Run tests to validate your implementation
4. Check compilation with `cargo check`
5. Lint with `cargo clippy --all-targets --all-features`
