/// Application.
pub mod app;

/// Widget renderer.
pub mod ui;

/// Data model.
pub mod car;

extern crate ratatui;
use std::io;

use app::App;
use crossterm::{
    event::{DisableMouseCapture, Event, EventStream, KeyCode, KeyEvent, KeyModifiers},
    terminal::LeaveAlternateScreen,
};
use dittolive_ditto::prelude::DatabaseId;
use futures::TryStreamExt;
use ratatui::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create an application.
    let database_id = DatabaseId::from_env("DITTO_DATABASE_ID").unwrap();
    let shared_token = std::env::var("DITTO_SHARED_TOKEN").unwrap();
    let mut app = App::new(database_id, shared_token);
    app.start_pooling();

    // Initialize the terminal user interface.
    let backend = CrosstermBackend::new(io::stderr());
    let mut terminal = Terminal::new(backend)?;
    let mut events = EventStream::new();

    while let Some(event) = events.try_next().await? {
        match event {
            Event::Key(key_event) => handle_key_events(key_event, &mut app).await?,
            Event::Mouse(_) => {}
            Event::Resize(_, _) => {}
            _ => {}
        }

        terminal.draw(|f| ui::render(&mut app, f))?;

        if !app.running {
            break;
        }
    }

    // Exit the user interface.
    crossterm::terminal::disable_raw_mode()?;
    crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
    Ok(())
}

/// Handles the key events and updates the state of [`App`].
pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> anyhow::Result<()> {
    match key_event.code {
        // Exit application on `ESC` or `q`
        KeyCode::Esc | KeyCode::Char('q') => {
            app.quit();
        }
        // Exit application on `Ctrl-C`
        KeyCode::Char('c') | KeyCode::Char('C') => {
            if key_event.modifiers == KeyModifiers::CONTROL {
                app.quit();
            }
        }
        // Ditto operations
        KeyCode::Char('s') | KeyCode::Char('S') => app.toggle_sync(),
        KeyCode::Char('b') | KeyCode::Char('B') => app.toggle_cloud(),
        KeyCode::Char('p') | KeyCode::Char('P') => app.toggle_p2p(),
        // Car operation
        KeyCode::Char('a') | KeyCode::Char('A') => app.add_car().await,
        KeyCode::Char('d') | KeyCode::Char('D') => app.remove_car().await,
        // Car selector
        KeyCode::Up => match app.tabs.index {
            0 => app.select_previous_car(),
            1 => app.select_previous_peer(),
            _ => (),
        },
        KeyCode::Down => match app.tabs.index {
            0 => app.select_next_car(),
            1 => app.select_next_peer(),
            _ => (),
        },
        // Other handlers you could add here.
        KeyCode::Tab => {
            app.tabs.next();
        }
        _ => {}
    }
    Ok(())
}
