// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::key_util::get_input_sequence_for_key_event,
    crate::pty::Pty,
    crate::ui::{PointerEventResponse, ScrollContext, TerminalScene},
    anyhow::{Context as _, Error},
    carnelian::{
        color::Color,
        input::{self},
        render::Context as RenderContext,
        AppContext, Message, Size, ViewAssistant, ViewAssistantContext, ViewKey,
    },
    fidl_fuchsia_hardware_pty::WindowSize,
    fuchsia_async as fasync, fuchsia_trace as ftrace,
    fuchsia_zircon::{AsHandleRef, Signals},
    futures::{channel::mpsc, io::AsyncReadExt, select, FutureExt, StreamExt},
    log::error,
    std::{cell::RefCell, convert::TryFrom, ffi::CStr, fs::File, io::prelude::*, rc::Rc},
    term_model::{
        ansi::Processor,
        clipboard::Clipboard,
        config::Config,
        event::{Event, EventListener},
        grid::Scroll,
        index::{Column, Line, Point},
        term::SizeInfo,
        Term,
    },
};

#[cfg(test)]
use cstr::cstr;

const BYTE_BUFFER_MAX_SIZE: usize = 128;

struct ResizeEvent {
    window_size: WindowSize,
}

#[derive(Clone)]
struct AppContextWrapper {
    app_context: Option<AppContext>,
    test_sender: Option<mpsc::UnboundedSender<Message>>,
}

impl AppContextWrapper {
    fn request_render(&self, target: ViewKey) {
        if let Some(app_context) = &self.app_context {
            app_context.request_render(target);
        } else if let Some(sender) = &self.test_sender {
            sender
                .unbounded_send(Box::new("request_render"))
                .expect("Unable queue message to test_sender");
        }
    }

    #[cfg(test)]
    // Allows tests to observe what is sent to the app_context.
    fn use_test_sender(&mut self, sender: mpsc::UnboundedSender<Message>) {
        self.app_context = None;
        self.test_sender = Some(sender);
    }
}

struct PtyContext {
    resize_sender: mpsc::UnboundedSender<ResizeEvent>,
    file: File,
    resize_receiver: Option<mpsc::UnboundedReceiver<ResizeEvent>>,
    test_buffer: Option<Vec<u8>>,
}

impl PtyContext {
    fn from_pty(pty: &Pty) -> Result<PtyContext, Error> {
        let (resize_sender, resize_receiver) = mpsc::unbounded();
        let file = pty.try_clone_fd()?;
        Ok(PtyContext {
            resize_sender,
            file,
            resize_receiver: Some(resize_receiver),
            test_buffer: None,
        })
    }

    fn take_resize_receiver(&mut self) -> mpsc::UnboundedReceiver<ResizeEvent> {
        self.resize_receiver.take().expect("attempting to take resize receiver")
    }

    #[cfg(test)]
    fn allow_dual_write_for_test(&mut self) {
        self.test_buffer = Some(vec![]);
    }
}

impl Write for PtyContext {
    fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
        if let Some(test_buffer) = self.test_buffer.as_mut() {
            for b in buf {
                test_buffer.push(*b);
            }
        }
        self.file.write(buf)
    }

    fn flush(&mut self) -> Result<(), std::io::Error> {
        self.file.flush()
    }
}

struct EventProxy {
    app_context: AppContextWrapper,
    view_key: ViewKey,
}

impl EventListener for EventProxy {
    fn send_event(&self, event: Event) {
        match event {
            Event::MouseCursorDirty => {
                self.app_context.request_render(self.view_key);
            }
            _ => (),
        }
    }
}

/// Empty type for term model config
struct UIConfig;

impl Default for UIConfig {
    fn default() -> UIConfig {
        UIConfig
    }
}

type TerminalConfig = Config<UIConfig>;

trait PointerEventResponseHandler {
    /// Signals that the struct should queue a view update.
    fn update_view(&mut self);

    fn scroll_term(&mut self, scroll: Scroll);
}

struct PointerEventResponseHandlerImpl<'a> {
    ctx: &'a mut ViewAssistantContext,
    term: Rc<RefCell<Term<EventProxy>>>,
}

impl PointerEventResponseHandler for PointerEventResponseHandlerImpl<'_> {
    fn update_view(&mut self) {
        self.ctx.request_render();
    }

    fn scroll_term(&mut self, scroll: Scroll) {
        let mut term = self.term.borrow_mut();
        term.scroll_display(scroll);
    }
}

pub struct TerminalViewAssistant {
    last_known_size: Size,
    last_known_size_info: SizeInfo,
    pty_context: Option<PtyContext>,
    terminal_scene: TerminalScene,
    term: Rc<RefCell<Term<EventProxy>>>,
    app_context: AppContextWrapper,
    view_key: ViewKey,

    /// If set, will use this command when spawning the pty, this is useful for tests.
    spawn_command: Option<&'static CStr>,
}

impl TerminalViewAssistant {
    /// Creates a new instance of the TerminalViewAssistant.
    pub fn new(app_context: &AppContext, view_key: ViewKey) -> TerminalViewAssistant {
        let cell_size = Size::new(12.0, 22.0);
        let size_info = SizeInfo {
            // set the initial size/width to be that of the cell size which prevents
            // the term from panicing if a byte is received before a resize event.
            width: cell_size.width,
            height: cell_size.height,
            cell_width: cell_size.width,
            cell_height: cell_size.height,
            padding_x: 0.0,
            padding_y: 0.0,
            dpr: 1.0,
        };

        let app_context =
            AppContextWrapper { app_context: Some(app_context.clone()), test_sender: None };

        let event_proxy = EventProxy { app_context: app_context.clone(), view_key };

        let term = Term::new(&TerminalConfig::default(), &size_info, Clipboard::new(), event_proxy);

        TerminalViewAssistant {
            last_known_size: Size::zero(),
            last_known_size_info: size_info,
            pty_context: None,
            term: Rc::new(RefCell::new(term)),
            terminal_scene: TerminalScene::new(Color::new()),
            app_context,
            view_key,
            spawn_command: None,
        }
    }

    #[cfg(test)]
    pub fn new_for_test() -> TerminalViewAssistant {
        let app_context = AppContext::new_for_testing_purposes_only();
        let mut view = Self::new(&app_context, 1);
        view.spawn_command = Some(cstr!("/pkg/bin/sh"));
        view
    }

    /// Checks if we need to perform a resize based on a new size.
    /// This method rounds pixels down to the next pixel value.
    fn needs_resize(prev_size: &Size, new_size: &Size) -> bool {
        prev_size.floor().not_equal(new_size.floor()).any()
    }

    /// Checks to see if the size of terminal has changed and resizes if it has.
    fn resize_if_needed(&mut self, new_size: &Size, metrics: &Size) -> Result<(), Error> {
        // The shell works on logical size units but the views operate based on the size
        if TerminalViewAssistant::needs_resize(&self.last_known_size, new_size) {
            let floored_size = new_size.floor();
            let term_size = TerminalScene::calculate_term_size_from_size(&floored_size);

            // we can safely call borrow_mut here because we are running the terminal
            // in single threaded mode. If we do move to a multithreaded model we will
            // get a compiler error since we are using spawn_local in our pty_loop.
            let mut term = self.term.borrow_mut();
            let last_size_info = self.last_known_size_info.clone();

            let cell_width = last_size_info.cell_width;
            let cell_height = last_size_info.cell_height;
            let padding_x = last_size_info.padding_x;
            let padding_y = last_size_info.padding_y;
            let dpr = metrics.width.min(metrics.height) as f64;

            let term_size_info = SizeInfo {
                width: term_size.width,
                height: term_size.height,
                cell_width,
                cell_height,
                padding_x,
                padding_y,
                dpr,
            };

            term.resize(&term_size_info);
            drop(term);

            let window_size =
                WindowSize { width: new_size.width as u32, height: new_size.height as u32 };

            self.queue_resize_event(ResizeEvent { window_size })
                .context("unable to queue outgoing pty message")?;

            self.last_known_size = floored_size;
            self.last_known_size_info = term_size_info;
            self.terminal_scene.update_size(floored_size, Size::new(cell_width, cell_height));
        }
        Ok(())
    }

    /// Checks to see if the Pty has been spawned and if not it does so.
    fn spawn_pty_loop(&mut self) -> Result<(), Error> {
        if self.pty_context.is_some() {
            return Ok(());
        }

        let mut pty = Pty::new()?;
        let mut pty_context = PtyContext::from_pty(&pty)?;
        let mut resize_receiver = pty_context.take_resize_receiver();

        let app_context = self.app_context.clone();
        let view_key = self.view_key;

        let term_clone = self.term.clone();
        let spawn_command = self.spawn_command.clone();

        // We want spawn_local here to enforce the single threaded model. If we
        // do move to multithreaded we will need to refactor the term parsing
        // logic to account for thread safaty.
        fasync::Task::local(async move {
            pty.spawn(spawn_command).await.expect("unable to spawn pty");

            let fd = pty.try_clone_fd().expect("unable to clone pty read fd");
            let mut evented_fd = unsafe {
                // EventedFd::new() is unsafe because it can't guarantee the lifetime of
                // the file descriptor passed to it exceeds the lifetime of the EventedFd.
                // Since we're cloning the file when passing it in, the EventedFd
                // effectively owns that file descriptor and thus controls it's lifetime.
                fasync::net::EventedFd::new(fd).expect("failed to create evented_fd for io_loop")
            };

            let mut write_fd = pty.try_clone_fd().expect("unable to clone pty write fd");
            let mut parser = Processor::new();

            let mut read_buf = [0u8; BYTE_BUFFER_MAX_SIZE];
            loop {
                let mut read_fut = evented_fd.read(&mut read_buf).fuse();
                select!(
                    result = read_fut => {
                        let read_count = result.unwrap_or_else(|e: std::io::Error| {
                            error!(
                                "failed to read bytes from io_loop, dropping current message: {:?}",
                                e
                            );
                            0
                        });
                        ftrace::duration!("terminal", "parse_bytes", "len" => read_count as u32);
                        let mut term = term_clone.borrow_mut();
                        if read_count > 0 {
                            for byte in &read_buf[0..read_count] {
                                parser.advance(&mut *term, *byte, &mut write_fd);
                            }
                            app_context.request_render(view_key);
                        }
                    },
                    result = resize_receiver.next().fuse() => {
                        if let Some(event) = result {
                            pty.resize(event.window_size).await.unwrap_or_else(|e: anyhow::Error| {
                                error!("failed to send resize message to pty: {:?}", e)
                            });
                            app_context.request_render(view_key);
                        }
                    }
                );
                if !pty.is_shell_process_running() {
                    break;
                }
            }
            // TODO(fxb/60181): Exit by using Carnelian, when implemented.
            std::process::exit(
                match pty.shell_process_info().map(|info| i32::try_from(info.return_code)) {
                    Some(Ok(return_code)) => return_code,
                    _ => {
                        error!("failed to obtain the shell process return code");
                        1
                    }
                },
            );
        })
        .detach();

        self.pty_context = Some(pty_context);

        Ok(())
    }

    fn queue_resize_event(&mut self, event: ResizeEvent) -> Result<(), Error> {
        if let Some(pty_context) = &mut self.pty_context {
            pty_context.resize_sender.unbounded_send(event).context("Unable send resize event")?;
        }

        Ok(())
    }

    // This method is overloaded from the ViewAssistant trait so we can test the method.
    // The ViewAssistant trait requires a ViewAssistantContext which we do not use and
    // we cannot make. This allows us to call the method directly in the tests.
    fn handle_keyboard_event_internal(
        &mut self,
        event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        if let Some(string) = get_input_sequence_for_key_event(event) {
            // In practice these writes will contain a small amount of data
            // so we can use a synchronous write. If that proves to not be the
            // case we will need to refactor to have buffered writing.
            if let Some(pty_context) = &mut self.pty_context {
                pty_context
                    .write_all(string.as_bytes())
                    .unwrap_or_else(|e| println!("failed to write character to pty: {}", e));
            }
        }

        Ok(())
    }

    /// Handles the pointer event response.
    fn handle_pointer_event_response<'a, T: PointerEventResponseHandler>(
        &mut self,
        response: PointerEventResponse,
        handler: &'a mut T,
    ) {
        match response {
            PointerEventResponse::ScrollLines(lines) => {
                handler.scroll_term(Scroll::Lines(lines));
            }
            PointerEventResponse::ViewDirty => handler.update_view(),
        }
    }
}

impl ViewAssistant for TerminalViewAssistant {
    fn setup(&mut self, _context: &ViewAssistantContext) -> Result<(), Error> {
        Ok(())
    }

    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: fuchsia_zircon::Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        ftrace::duration!("terminal", "TerminalViewAssistant:render");

        // we need to call spawn in this update block because calling it in the
        // setup method causes us to receive write events before the view is
        // prepared to draw.
        self.spawn_pty_loop()?;
        self.resize_if_needed(&context.size, &context.metrics)?;

        // Tell the termnial scene to render the values
        let config = TerminalConfig::default();
        let term = self.term.borrow();

        let iter = {
            ftrace::duration!("terminal", "TerminalViewAssistant:update:renderable_cells");
            term.renderable_cells(&config)
        };

        let grid = term.grid();

        let scroll_context = ScrollContext {
            history: grid.history_size(),
            visible_lines: *grid.num_lines(),
            display_offset: grid.display_offset(),
        };
        self.terminal_scene.update_scroll_context(scroll_context);

        // Write the grid to inspect for e2e testing. The contents will trim all whitespace
        // from either end of the string which means that the trailing space after the prompt
        // will not be included.
        let bottom = grid.display_offset();
        let top = bottom + *grid.num_lines() - 1;

        let txt = term.bounds_to_string(
            Point::new(*Line(top), Column(0)),
            Point::new(*Line(bottom), grid.num_cols()),
        );
        fuchsia_inspect::component::inspector().root().record_string("grid", txt.trim());

        drop(grid);

        self.terminal_scene.render(render_context, context, iter);
        ready_event.as_handle_ref().signal(Signals::NONE, Signals::EVENT_SIGNALED)?;
        Ok(())
    }

    fn handle_keyboard_event(
        &mut self,
        _context: &mut ViewAssistantContext,
        _event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        self.handle_keyboard_event_internal(keyboard_event)?;
        Ok(())
    }

    fn handle_pointer_event(
        &mut self,
        ctx: &mut ViewAssistantContext,
        _event: &input::Event,
        pointer_event: &input::pointer::Event,
    ) -> Result<(), Error> {
        if let Some(response) = self.terminal_scene.handle_pointer_event(&pointer_event, ctx) {
            let mut handler = PointerEventResponseHandlerImpl { ctx, term: self.term.clone() };
            self.handle_pointer_event_response(response, &mut handler);
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        anyhow::anyhow,
        fuchsia_async::{DurationExt, Timer},
        fuchsia_zircon::DurationNum,
        futures::future::Either,
        term_model::grid::Scroll,
    };

    fn unit_metrics() -> Size {
        Size::new(1.0, 1.0)
    }

    #[test]
    fn can_create_view() {
        let _ = TerminalViewAssistant::new_for_test();
    }

    #[fasync::run_singlethreaded(test)]
    async fn handle_pointer_event_response_updates_view_for_view_dirty() -> Result<(), Error> {
        let mut view = TerminalViewAssistant::new_for_test();
        let mut handler = TestPointerEventResponder::new();
        view.handle_pointer_event_response(PointerEventResponse::ViewDirty, &mut handler);
        assert_eq!(handler.update_count, 1);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn handle_pointer_event_response_does_not_update_view_for_scroll_lines(
    ) -> Result<(), Error> {
        let mut view = TerminalViewAssistant::new_for_test();

        let mut handler = TestPointerEventResponder::new();
        view.handle_pointer_event_response(PointerEventResponse::ScrollLines(1), &mut handler);
        assert_eq!(handler.update_count, 0);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn handle_pointer_event_response_scroll_lines_updates_grid() -> Result<(), Error> {
        let mut view = TerminalViewAssistant::new_for_test();

        let mut handler = TestPointerEventResponder::new();
        view.handle_pointer_event_response(PointerEventResponse::ScrollLines(1), &mut handler);

        assert_eq!(handler.scroll_offset, 1);
        Ok(())
    }

    #[test]
    fn needs_resize_false_for_zero_sizes() {
        let zero = Size::zero();
        assert_eq!(TerminalViewAssistant::needs_resize(&zero, &zero), false);
    }

    #[test]
    fn needs_resize_true_for_different_sizes() {
        let prev_size = Size::zero();
        let new_size = Size::new(100.0, 100.0);
        assert!(TerminalViewAssistant::needs_resize(&prev_size, &new_size));
    }

    #[test]
    fn needs_resize_true_different_width_same_height() {
        let prev_size = Size::new(100.0, 10.0);
        let new_size = Size::new(100.0, 100.0);
        assert!(TerminalViewAssistant::needs_resize(&prev_size, &new_size));
    }

    #[test]
    fn needs_resize_true_different_height_same_width() {
        let prev_size = Size::new(10.0, 100.0);
        let new_size = Size::new(100.0, 100.0);
        assert!(TerminalViewAssistant::needs_resize(&prev_size, &new_size));
    }

    #[test]
    fn needs_resize_false_when_rounding_down() {
        let prev_size = Size::new(100.0, 100.0);
        let new_size = Size::new(100.1, 100.0);
        assert_eq!(TerminalViewAssistant::needs_resize(&prev_size, &new_size), false);
    }

    #[test]
    fn term_is_resized_when_needed() {
        let mut view = TerminalViewAssistant::new_for_test();
        let new_size = Size::new(100.5, 100.9);
        view.resize_if_needed(&new_size, &unit_metrics()).expect("call to resize failed");

        let size_info = view.last_known_size_info.clone();
        let expected_size = TerminalScene::calculate_term_size_from_size(&view.last_known_size);

        // we want to make sure that the values are floored and that they
        // match what the scene will render the terminal as.
        assert_eq!(size_info.width, expected_size.width);
        assert_eq!(size_info.height, expected_size.height);
    }

    #[test]
    fn last_known_size_is_floored_on_resize() {
        let mut view = TerminalViewAssistant::new_for_test();
        let new_size = Size::new(100.3, 100.4);
        view.resize_if_needed(&new_size, &unit_metrics()).expect("call to resize failed");

        assert_eq!(view.last_known_size.width, 100.0);
        assert_eq!(view.last_known_size.height, 100.0);
    }

    #[fasync::run_singlethreaded(test)]
    async fn event_proxy_calls_view_update_on_dirty_mouse_cursor() -> Result<(), Error> {
        let (sender, mut receiver) = mpsc::unbounded();
        let app_context = AppContextWrapper { app_context: None, test_sender: Some(sender) };

        let event_proxy = EventProxy { app_context, view_key: 0 };

        event_proxy.send_event(Event::MouseCursorDirty);

        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":event_proxy_calls_view_update_on_dirty_mouse_cursor failed to get update")?;

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn scroll_display_triggers_call_to_redraw() -> Result<(), Error> {
        let (view, mut receiver) = make_test_view_with_spawned_pty_loop().await?;

        let event_proxy =
            EventProxy { app_context: view.app_context.clone(), view_key: view.view_key };

        let mut term = Term::new(
            &TerminalConfig::default(),
            &view.last_known_size_info,
            Clipboard::new(),
            event_proxy,
        );

        term.scroll_display(Scroll::Lines(1));

        // No redraw will trigger a timeout and failure
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":resize_message_triggers_call_to_redraw after queue event")?;

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn resize_message_queued_with_logical_size_when_resize_needed() -> Result<(), Error> {
        let pty = Pty::new()?;
        let mut pty_context = PtyContext::from_pty(&pty)?;
        let mut view = TerminalViewAssistant::new_for_test();
        let mut receiver = pty_context.take_resize_receiver();

        view.pty_context = Some(pty_context);

        view.resize_if_needed(&Size::new(1000.0, 2000.0), &unit_metrics())
            .expect("call to resize failed");

        let event = receiver.next().await.expect("failed to receive pty event");
        assert_eq!(event.window_size.width, 1000);
        assert_eq!(event.window_size.height, 2000);

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn handle_keyboard_event_writes_characters() -> Result<(), Error> {
        let pty = Pty::new()?;
        let mut pty_context = PtyContext::from_pty(&pty)?;
        let mut view = TerminalViewAssistant::new_for_test();
        pty_context.allow_dual_write_for_test();

        view.pty_context = Some(pty_context);

        let capital_a = 65;
        view.handle_keyboard_event_internal(&make_keyboard_event(capital_a))?;

        let test_buffer = view.pty_context.as_mut().unwrap().test_buffer.take().unwrap();
        assert_eq!(test_buffer, b"A");

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn pty_is_spawned_on_first_request() -> Result<(), Error> {
        let mut view = TerminalViewAssistant::new_for_test();
        view.spawn_pty_loop()?;
        assert!(view.pty_context.is_some());

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn pty_message_reads_trigger_call_to_redraw() -> Result<(), Error> {
        let (view, mut receiver) = make_test_view_with_spawned_pty_loop().await?;

        let mut fd = view
            .pty_context
            .as_ref()
            .map(|ctx| ctx.file.try_clone().expect("attempt to clone fd failed"))
            .unwrap();

        fasync::Task::local(async move {
            let _ = fd.write_all(b"ls");
        })
        .detach();

        // No redraw will trigger a timeout and failure
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":pty_message_reads_trigger_call_to_redraw after write")?;

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn resize_message_triggers_call_to_redraw() -> Result<(), Error> {
        let (mut view, mut receiver) = make_test_view_with_spawned_pty_loop().await?;

        let window_size = WindowSize { width: 123, height: 123 };

        view.queue_resize_event(ResizeEvent { window_size })
            .context("unable to queue outgoing pty message")?;

        // No redraw will trigger a timeout and failure
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":resize_message_triggers_call_to_redraw after queue event")?;

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    #[ignore] // TODO(fxbug.dev/52560) re-enable this test when de-flaked
    async fn bytes_written_are_processed_by_term() -> Result<(), Error> {
        let (mut view, mut receiver) = make_test_view_with_spawned_pty_loop().await?;

        // make sure we have a big enough size that a single character does not wrap
        let large_size = Size::new(1000.0, 1000.0);
        view.resize_if_needed(&large_size, &unit_metrics())?;

        // Resizing will cause an update so we need to wait for that before we write.
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":bytes_written_are_processed_by_term after resize_if_needed")?;

        let term = view.term.borrow();

        let col_pos_before = term.cursor().point.col;
        drop(term);

        let mut fd = view
            .pty_context
            .as_ref()
            .map(|ctx| ctx.file.try_clone().expect("attempt to clone fd failed"))
            .unwrap();

        fasync::Task::local(async move {
            let _ = fd.write_all(b"A");
        })
        .detach();

        // Wait until we get a notice that the view is ready to redraw
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context(":bytes_written_are_processed_by_term after write")?;

        let term = view.term.borrow();
        let col_pos_after = term.cursor().point.col;
        assert_eq!(col_pos_before + 1, col_pos_after);

        Ok(())
    }

    async fn make_test_view_with_spawned_pty_loop(
    ) -> Result<(TerminalViewAssistant, mpsc::UnboundedReceiver<Message>), Error> {
        let (sender, mut receiver) = mpsc::unbounded();

        let mut view = TerminalViewAssistant::new_for_test();
        view.app_context.use_test_sender(sender);

        let _ = view.spawn_pty_loop();

        // Spawning the loop triggers a read and a redraw, we want to skip this
        // so that we can check that our test event triggers the redraw.
        wait_until_update_received_or_timeout(&mut receiver)
            .await
            .context("::make_test_view_with_spawned_pty_loop")?;

        Ok((view, receiver))
    }

    async fn wait_until_update_received_or_timeout(
        receiver: &mut mpsc::UnboundedReceiver<Message>,
    ) -> Result<(), Error> {
        loop {
            let timeout = Timer::new(5000_i64.millis().after_now());
            let either = futures::future::select(timeout, receiver.next().fuse());
            let resolved = either.await;
            match resolved {
                Either::Left(_) => {
                    return Err(anyhow!("wait_until_update_received timed out"));
                }
                Either::Right((result, _)) => {
                    let _ = result.expect("result should not be None");
                    break;
                }
            }
        }
        Ok(())
    }

    fn make_keyboard_event(code_point: u32) -> input::keyboard::Event {
        input::keyboard::Event {
            code_point: Some(code_point),
            phase: input::keyboard::Phase::Pressed,
            hid_usage: 0 as u32,
            modifiers: input::Modifiers::default(),
        }
    }

    struct TestPointerEventResponder {
        update_count: usize,
        scroll_offset: isize,
    }

    impl TestPointerEventResponder {
        fn new() -> TestPointerEventResponder {
            TestPointerEventResponder { update_count: 0, scroll_offset: 0 }
        }
    }

    impl PointerEventResponseHandler for TestPointerEventResponder {
        fn update_view(&mut self) {
            self.update_count += 1;
        }

        fn scroll_term(&mut self, scroll: Scroll) {
            match scroll {
                Scroll::Lines(lines) => self.scroll_offset += lines,
                _ => (),
            }
        }
    }
}
