use std::{cell::OnceCell, future::Future, rc::Rc, time::Duration};

use futures_util::FutureExt;
use ratatui::crossterm::event;
use thecockpit::app::{App, AppExecutor};

struct TokioExecutor;

impl AppExecutor for TokioExecutor {
    fn execute<T: 'static>(
        &self,
        future: impl Future<Output = T> + 'static,
        output_cell: Rc<OnceCell<T>>,
    ) {
        tokio::task::spawn_local(future.map(move |output| output_cell.set(output)));
    }
}

fn main() {
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap();

    let local = tokio::task::LocalSet::new();

    local.spawn_local(async {
        let mut terminal = ratatui::init();
        let mut app = App::new(TokioExecutor);

        loop {
            terminal.draw(|frame| app.draw(frame)).unwrap();

            if event::poll(Duration::from_secs(0)).unwrap() {
                match event::read().unwrap() {
                    event::Event::Key(event::KeyEvent {
                        code: event::KeyCode::Char('q'),
                        ..
                    }) => break,
                    event::Event::Key(event::KeyEvent {
                        code: event::KeyCode::Left,
                        ..
                    }) => app.prev_tab(),
                    event::Event::Key(event::KeyEvent {
                        code: event::KeyCode::Right,
                        ..
                    }) => app.next_tab(),
                    event::Event::Key(event::KeyEvent {
                        code: event::KeyCode::Char(c),
                        ..
                    }) => app.add_char_to_number_guess(c),
                    _ => {}
                }
            }

            tokio::task::yield_now().await;
        }

        ratatui::restore();
    });

    rt.block_on(local);
}
