// 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::input_device::{self, Handled, InputDeviceBinding, InputEvent},
    crate::utils::{Position, Size},
    anyhow::{format_err, Error},
    async_trait::async_trait,
    fidl_fuchsia_input_report as fidl_input_report,
    fidl_fuchsia_input_report::{InputDeviceProxy, InputReport},
    fidl_fuchsia_ui_input as fidl_ui_input, fidl_fuchsia_ui_pointerinjector as pointerinjector,
    fuchsia_syslog::fx_log_err,
    fuchsia_zircon as zx,
    futures::channel::mpsc::Sender,
    maplit::hashmap,
    std::collections::HashMap,
    std::iter::FromIterator,
};

/// A [`TouchEvent`] represents a set of contacts and the phase those contacts are in.
///
/// For example, when a user touches a touch screen with two fingers, there will be two
/// [`TouchContact`]s. When a user removes one finger, there will still be two contacts
/// but one will be reported as removed.
///
/// The expected sequence for any given contact is:
/// 1. [`fidl_fuchsia_ui_input::PointerEventPhase::Add`]
/// 2. [`fidl_fuchsia_ui_input::PointerEventPhase::Down`]
/// 3. 0 or more [`fidl_fuchsia_ui_input::PointerEventPhase::Move`]
/// 4. [`fidl_fuchsia_ui_input::PointerEventPhase::Up`]
/// 5. [`fidl_fuchsia_ui_input::PointerEventPhase::Remove`]
///
/// Additionally, a [`fidl_fuchsia_ui_input::PointerEventPhase::Cancel`] may be sent at any time
/// signalling that the event is no longer directed towards the receiver.
#[derive(Clone, Debug, PartialEq)]
pub struct TouchEvent {
    /// Deprecated. To be removed with fxbug.dev/75817.
    /// The contacts associated with the touch event. For example, a two-finger touch would result
    /// in one touch event with two [`TouchContact`]s.
    ///
    /// Contacts are grouped based on their current phase (e.g., down, move).
    pub contacts: HashMap<fidl_ui_input::PointerEventPhase, Vec<TouchContact>>,

    /// The contacts associated with the touch event. For example, a two-finger touch would result
    /// in one touch event with two [`TouchContact`]s.
    ///
    /// Contacts are grouped based on their current phase (e.g., add, change).
    pub injector_contacts: HashMap<pointerinjector::EventPhase, Vec<TouchContact>>,
}

/// [`TouchDeviceType`] indicates the type of touch device. Both Touch Screen and Windows Precision
/// Touchpad send touch event from driver but need different process inside input pipeline.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TouchDeviceType {
    TouchScreen,
    WindowsPrecisionTouchpad,
}

/// A [`TouchContact`] represents a single contact (e.g., one touch of a multi-touch gesture) related
/// to a touch event.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TouchContact {
    /// The identifier of the contact. Unique per touch device.
    pub id: u32,

    /// The position of the touch event, in the units of the associated
    /// [`ContactDeviceDescriptor`]'s `range`.
    pub position: Position,

    /// The pressure associated with the contact, in the units of the associated
    /// [`ContactDeviceDescriptor`]'s `pressure_range`.
    pub pressure: Option<i64>,

    /// The size of the touch event, in the units of the associated
    /// [`ContactDeviceDescriptor`]'s `range`.
    pub contact_size: Option<Size>,
}

impl Eq for TouchContact {}

impl From<&fidl_fuchsia_input_report::ContactInputReport> for TouchContact {
    fn from(fidl_contact: &fidl_fuchsia_input_report::ContactInputReport) -> TouchContact {
        let contact_size =
            if fidl_contact.contact_width.is_some() && fidl_contact.contact_height.is_some() {
                Some(Size {
                    width: fidl_contact.contact_width.unwrap() as f32,
                    height: fidl_contact.contact_height.unwrap() as f32,
                })
            } else {
                None
            };

        TouchContact {
            id: fidl_contact.contact_id.unwrap_or_default(),
            position: Position {
                x: fidl_contact.position_x.unwrap_or_default() as f32,
                y: fidl_contact.position_y.unwrap_or_default() as f32,
            },
            pressure: fidl_contact.pressure,
            contact_size,
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TouchDeviceDescriptor {
    /// The id of the connected touch input device.
    pub device_id: u32,

    /// The descriptors for the possible contacts associated with the device.
    pub contacts: Vec<ContactDeviceDescriptor>,
}

/// A [`ContactDeviceDescriptor`] describes the possible values touch contact properties can take on.
///
/// This descriptor can be used, for example, to determine where on a screen a touch made contact.
///
/// # Example
///
/// ```
/// // Determine the scaling factor between the display and the touch device's x range.
/// let scaling_factor =
///     display_width / (contact_descriptor._x_range.end - contact_descriptor._x_range.start);
/// // Use the scaling factor to scale the contact report's x position.
/// let hit_location =
///     scaling_factor * (contact_report.position_x - contact_descriptor._x_range.start);
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ContactDeviceDescriptor {
    /// The range of possible x values for this touch contact.
    pub x_range: fidl_input_report::Range,

    /// The range of possible y values for this touch contact.
    pub y_range: fidl_input_report::Range,

    /// The range of possible pressure values for this touch contact.
    pub pressure_range: Option<fidl_input_report::Range>,

    /// The range of possible widths for this touch contact.
    pub width_range: Option<fidl_input_report::Range>,

    /// The range of possible heights for this touch contact.
    pub height_range: Option<fidl_input_report::Range>,
}

/// A [`TouchBinding`] represents a connection to a touch input device.
///
/// The [`TouchBinding`] parses and exposes touch descriptor properties (e.g., the range of
/// possible x values for touch contacts) for the device it is associated with.
/// It also parses [`InputReport`]s from the device, and sends them to the device binding owner over
/// `event_sender`.
pub struct TouchBinding {
    /// The channel to stream InputEvents to.
    event_sender: Sender<InputEvent>,

    /// Holds information about this device.
    device_descriptor: TouchDeviceDescriptor,

    /// Touch device type of the touch device.
    /// TODO(fxb/99687): following CL will begin use this field and remove the underscore.
    _touch_device_type: TouchDeviceType,
}

#[async_trait]
impl input_device::InputDeviceBinding for TouchBinding {
    fn input_event_sender(&self) -> Sender<InputEvent> {
        self.event_sender.clone()
    }

    fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
        input_device::InputDeviceDescriptor::Touch(self.device_descriptor.clone())
    }
}

impl TouchBinding {
    /// Creates a new [`InputDeviceBinding`] from the `device_proxy`.
    ///
    /// The binding will start listening for input reports immediately and send new InputEvents
    /// to the device binding owner over `input_event_sender`.
    ///
    /// # Parameters
    /// - `device_proxy`: The proxy to bind the new [`InputDeviceBinding`] to.
    /// - `device_id`: The id of the connected touch device.
    /// - `input_event_sender`: The channel to send new InputEvents to.
    ///
    /// # Errors
    /// If there was an error binding to the proxy.
    pub async fn new(
        device_proxy: InputDeviceProxy,
        device_id: u32,
        input_event_sender: Sender<input_device::InputEvent>,
    ) -> Result<Self, Error> {
        let device_binding =
            Self::bind_device(&device_proxy, device_id, input_event_sender).await?;
        input_device::initialize_report_stream(
            device_proxy,
            device_binding.get_device_descriptor(),
            device_binding.input_event_sender(),
            Self::process_reports,
        );

        Ok(device_binding)
    }

    /// Binds the provided input device to a new instance of `Self`.
    ///
    /// # Parameters
    /// - `device`: The device to use to initialize the binding.
    /// - `device_id`: The id of the connected touch device.
    /// - `input_event_sender`: The channel to send new InputEvents to.
    ///
    /// # Errors
    /// If the device descriptor could not be retrieved, or the descriptor could not be parsed
    /// correctly.
    async fn bind_device(
        device: &InputDeviceProxy,
        device_id: u32,
        input_event_sender: Sender<input_device::InputEvent>,
    ) -> Result<Self, Error> {
        let device_descriptor: fidl_fuchsia_input_report::DeviceDescriptor =
            device.get_descriptor().await?;

        match device_descriptor.touch {
            Some(fidl_fuchsia_input_report::TouchDescriptor {
                input:
                    Some(fidl_fuchsia_input_report::TouchInputDescriptor {
                        contacts: Some(contact_descriptors),
                        max_contacts: _,
                        touch_type: _,
                        buttons: _,
                        ..
                    }),
                ..
            }) => Ok(TouchBinding {
                event_sender: input_event_sender,
                device_descriptor: TouchDeviceDescriptor {
                    device_id,
                    contacts: contact_descriptors
                        .iter()
                        .map(TouchBinding::parse_contact_descriptor)
                        .filter_map(Result::ok)
                        .collect(),
                },
                _touch_device_type: get_device_type(device).await,
            }),
            descriptor => Err(format_err!("Touch Descriptor failed to parse: \n {:?}", descriptor)),
        }
    }

    /// Parses an [`InputReport`] into one or more [`InputEvent`]s.
    ///
    /// The [`InputEvent`]s are sent to the device binding owner via [`input_event_sender`].
    ///
    /// # Parameters
    /// - `report`: The incoming [`InputReport`].
    /// - `previous_report`: The previous [`InputReport`] seen for the same device. This can be
    ///                    used to determine, for example, which keys are no longer present in
    ///                    a keyboard report to generate key released events. If `None`, no
    ///                    previous report was found.
    /// - `device_descriptor`: The descriptor for the input device generating the input reports.
    /// - `input_event_sender`: The sender for the device binding's input event stream.
    ///
    /// # Returns
    /// An [`InputReport`] which will be passed to the next call to [`process_reports`], as
    /// [`previous_report`]. If `None`, the next call's [`previous_report`] will be `None`.
    fn process_reports(
        report: InputReport,
        previous_report: Option<InputReport>,
        device_descriptor: &input_device::InputDeviceDescriptor,
        input_event_sender: &mut Sender<InputEvent>,
    ) -> Option<InputReport> {
        fuchsia_trace::duration!("input", "touch-binding-process-report");
        fuchsia_trace::flow_end!("input", "input_report", report.trace_id.unwrap_or(0));

        // Input devices can have multiple types so ensure `report` is a TouchInputReport.
        let touch_report: &fidl_fuchsia_input_report::TouchInputReport = match &report.touch {
            Some(touch) => touch,
            None => {
                return previous_report;
            }
        };

        let previous_contacts: HashMap<u32, TouchContact> = previous_report
            .as_ref()
            .and_then(|unwrapped_report| unwrapped_report.touch.as_ref())
            .map(touch_contacts_from_touch_report)
            .unwrap_or_default();
        let current_contacts: HashMap<u32, TouchContact> =
            touch_contacts_from_touch_report(touch_report);

        // Don't send an event if there are no new contacts.
        if previous_contacts.is_empty() && current_contacts.is_empty() {
            return Some(report);
        }

        // Contacts which exist only in current.
        let added_contacts: Vec<TouchContact> = Vec::from_iter(
            current_contacts
                .values()
                .cloned()
                .filter(|contact| !previous_contacts.contains_key(&contact.id)),
        );
        // Contacts which exist in both previous and current.
        let moved_contacts: Vec<TouchContact> = Vec::from_iter(
            current_contacts
                .values()
                .cloned()
                .filter(|contact| previous_contacts.contains_key(&contact.id)),
        );
        // Contacts which exist only in previous.
        let removed_contacts: Vec<TouchContact> = Vec::from_iter(
            previous_contacts
                .values()
                .cloned()
                .filter(|contact| !current_contacts.contains_key(&contact.id)),
        );

        let event_time: zx::Time = input_device::event_time_or_now(report.event_time);

        let trace_id = fuchsia_trace::generate_nonce();
        fuchsia_trace::flow_begin!("input", "report-to-event", trace_id);
        send_event(
            hashmap! {
                fidl_ui_input::PointerEventPhase::Add => added_contacts.clone(),
                fidl_ui_input::PointerEventPhase::Down => added_contacts.clone(),
                fidl_ui_input::PointerEventPhase::Move => moved_contacts.clone(),
                fidl_ui_input::PointerEventPhase::Up => removed_contacts.clone(),
                fidl_ui_input::PointerEventPhase::Remove => removed_contacts.clone(),
            },
            hashmap! {
                pointerinjector::EventPhase::Add => added_contacts,
                pointerinjector::EventPhase::Change => moved_contacts,
                pointerinjector::EventPhase::Remove => removed_contacts,
            },
            device_descriptor,
            event_time,
            input_event_sender,
            trace_id,
        );

        Some(report)
    }

    /// Parses a fidl_input_report contact descriptor into a [`ContactDeviceDescriptor`]
    ///
    /// # Parameters
    /// - `contact_device_descriptor`: The contact descriptor to parse.
    ///
    /// # Errors
    /// If the contact description fails to parse because required fields aren't present.
    fn parse_contact_descriptor(
        contact_device_descriptor: &fidl_input_report::ContactInputDescriptor,
    ) -> Result<ContactDeviceDescriptor, Error> {
        match contact_device_descriptor {
            fidl_input_report::ContactInputDescriptor {
                position_x: Some(x_axis),
                position_y: Some(y_axis),
                pressure: pressure_axis,
                contact_width: width_axis,
                contact_height: height_axis,
                ..
            } => Ok(ContactDeviceDescriptor {
                x_range: x_axis.range,
                y_range: y_axis.range,
                pressure_range: pressure_axis.map(|axis| axis.range),
                width_range: width_axis.map(|axis| axis.range),
                height_range: height_axis.map(|axis| axis.range),
            }),
            descriptor => {
                Err(format_err!("Touch Contact Descriptor failed to parse: \n {:?}", descriptor))
            }
        }
    }
}

fn touch_contacts_from_touch_report(
    touch_report: &fidl_fuchsia_input_report::TouchInputReport,
) -> HashMap<u32, TouchContact> {
    // First unwrap all the optionals in the input report to get to the contacts.
    let contacts: Vec<TouchContact> = touch_report
        .contacts
        .as_ref()
        .and_then(|unwrapped_contacts| {
            // Once the contacts are found, convert them into `TouchContact`s.
            Some(unwrapped_contacts.iter().map(TouchContact::from).collect())
        })
        .unwrap_or_default();

    contacts.into_iter().map(|contact| (contact.id, contact)).collect()
}

/// Sends a TouchEvent over `input_event_sender`.
///
/// # Parameters
/// - `contacts`: The contact points relevant to the new TouchEvent.
/// - `injector_contacts`: The contact points relevant to the new TouchEvent, used to send
///                        pointer events into Scenic.
/// - `device_descriptor`: The descriptor for the input device generating the input reports.
/// - `event_time`: The time in nanoseconds when the event was first recorded.
/// - `input_event_sender`: The sender for the device binding's input event stream.
fn send_event(
    contacts: HashMap<fidl_ui_input::PointerEventPhase, Vec<TouchContact>>,
    injector_contacts: HashMap<pointerinjector::EventPhase, Vec<TouchContact>>,
    device_descriptor: &input_device::InputDeviceDescriptor,
    event_time: zx::Time,
    input_event_sender: &mut Sender<input_device::InputEvent>,
    trace_id: u64,
) {
    match input_event_sender.try_send(input_device::InputEvent {
        device_event: input_device::InputDeviceEvent::Touch(TouchEvent {
            contacts,
            injector_contacts,
        }),
        device_descriptor: device_descriptor.clone(),
        event_time,
        handled: Handled::No,
        trace_id: Some(trace_id),
    }) {
        Err(e) => fx_log_err!("Failed to send TouchEvent with error: {:?}", e),
        _ => {}
    }
}

/// [`get_device_type`] check if the touch device is a touchscreen or Windows Precision Touchpad.
///
/// Windows Precision Touchpad reports `MouseCollection` or `WindowsPrecisionTouchpadCollection`
/// in `TouchFeatureReport`. Fallback all error responses on `get_feature_report` to TouchScreen
/// because some touch screen does not report this method.
async fn get_device_type(input_device: &fidl_input_report::InputDeviceProxy) -> TouchDeviceType {
    match input_device.get_feature_report().await {
        Ok(Ok(fidl_input_report::FeatureReport {
            touch:
                Some(fidl_input_report::TouchFeatureReport {
                    input_mode:
                        Some(
                            fidl_input_report::TouchConfigurationInputMode::MouseCollection
                            | fidl_input_report::TouchConfigurationInputMode::WindowsPrecisionTouchpadCollection,
                        ),
                    ..
                }),
            ..
        })) => TouchDeviceType::WindowsPrecisionTouchpad,
        _ => TouchDeviceType::TouchScreen,
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::testing_utilities::{
            self, create_touch_contact, create_touch_event, create_touch_input_report,
        },
        crate::utils::Position,
        assert_matches::assert_matches,
        fidl::endpoints::spawn_stream_handler,
        fuchsia_async as fasync,
        futures::StreamExt,
        pretty_assertions::assert_eq,
        test_case::test_case,
    };

    #[fasync::run_singlethreaded(test)]
    async fn process_empty_reports() {
        let previous_report_time = fuchsia_zircon::Time::get_monotonic().into_nanos();
        let previous_report = create_touch_input_report(vec![], previous_report_time);
        let report_time = fuchsia_zircon::Time::get_monotonic().into_nanos();
        let report = create_touch_input_report(vec![], report_time);

        let descriptor = input_device::InputDeviceDescriptor::Touch(TouchDeviceDescriptor {
            device_id: 1,
            contacts: vec![],
        });
        let (mut event_sender, mut event_receiver) = futures::channel::mpsc::channel(1);
        let returned_report = TouchBinding::process_reports(
            report,
            Some(previous_report),
            &descriptor,
            &mut event_sender,
        );
        assert!(returned_report.is_some());
        assert_eq!(returned_report.unwrap().event_time, Some(report_time));

        // Assert there are no pending events on the receiver.
        let event = event_receiver.try_next();
        assert!(event.is_err());
    }

    // Tests that a input report with a new contact generates an event with an add and a down.
    #[fasync::run_singlethreaded(test)]
    async fn add_and_down() {
        const TOUCH_ID: u32 = 2;

        let descriptor = input_device::InputDeviceDescriptor::Touch(TouchDeviceDescriptor {
            device_id: 1,
            contacts: vec![],
        });
        let (event_time_i64, event_time_u64) = testing_utilities::event_times();

        let contact = fidl_fuchsia_input_report::ContactInputReport {
            contact_id: Some(TOUCH_ID),
            position_x: Some(0),
            position_y: Some(0),
            pressure: None,
            contact_width: None,
            contact_height: None,
            ..fidl_fuchsia_input_report::ContactInputReport::EMPTY
        };
        let reports = vec![create_touch_input_report(vec![contact], event_time_i64)];

        let expected_events = vec![create_touch_event(
            hashmap! {
                fidl_ui_input::PointerEventPhase::Add
                    => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
                fidl_ui_input::PointerEventPhase::Down
                    => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
            },
            event_time_u64,
            &descriptor,
        )];

        assert_input_report_sequence_generates_events!(
            input_reports: reports,
            expected_events: expected_events,
            device_descriptor: descriptor,
            device_type: TouchBinding,
        );
    }

    // Tests that up and remove events are sent when a touch is released.
    #[fasync::run_singlethreaded(test)]
    async fn up_and_remove() {
        const TOUCH_ID: u32 = 2;

        let descriptor = input_device::InputDeviceDescriptor::Touch(TouchDeviceDescriptor {
            device_id: 1,
            contacts: vec![],
        });
        let (event_time_i64, event_time_u64) = testing_utilities::event_times();

        let contact = fidl_fuchsia_input_report::ContactInputReport {
            contact_id: Some(TOUCH_ID),
            position_x: Some(0),
            position_y: Some(0),
            pressure: None,
            contact_width: None,
            contact_height: None,
            ..fidl_fuchsia_input_report::ContactInputReport::EMPTY
        };
        let reports = vec![
            create_touch_input_report(vec![contact], event_time_i64),
            create_touch_input_report(vec![], event_time_i64),
        ];

        let expected_events = vec![
            create_touch_event(
                hashmap! {
                    fidl_ui_input::PointerEventPhase::Add
                        => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
                    fidl_ui_input::PointerEventPhase::Down
                        => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
                },
                event_time_u64,
                &descriptor,
            ),
            create_touch_event(
                hashmap! {
                    fidl_ui_input::PointerEventPhase::Up
                        => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
                    fidl_ui_input::PointerEventPhase::Remove
                        => vec![create_touch_contact(TOUCH_ID, Position { x: 0.0, y: 0.0 })],
                },
                event_time_u64,
                &descriptor,
            ),
        ];

        assert_input_report_sequence_generates_events!(
            input_reports: reports,
            expected_events: expected_events,
            device_descriptor: descriptor,
            device_type: TouchBinding,
        );
    }

    // Tests that a move generates the correct event.
    #[fasync::run_singlethreaded(test)]
    async fn add_down_move() {
        const TOUCH_ID: u32 = 2;
        let first = Position { x: 10.0, y: 30.0 };
        let second = Position { x: first.x * 2.0, y: first.y * 2.0 };

        let descriptor = input_device::InputDeviceDescriptor::Touch(TouchDeviceDescriptor {
            device_id: 1,
            contacts: vec![],
        });
        let (event_time_i64, event_time_u64) = testing_utilities::event_times();

        let first_contact = fidl_fuchsia_input_report::ContactInputReport {
            contact_id: Some(TOUCH_ID),
            position_x: Some(first.x as i64),
            position_y: Some(first.y as i64),
            pressure: None,
            contact_width: None,
            contact_height: None,
            ..fidl_fuchsia_input_report::ContactInputReport::EMPTY
        };
        let second_contact = fidl_fuchsia_input_report::ContactInputReport {
            contact_id: Some(TOUCH_ID),
            position_x: Some(first.x as i64 * 2),
            position_y: Some(first.y as i64 * 2),
            pressure: None,
            contact_width: None,
            contact_height: None,
            ..fidl_fuchsia_input_report::ContactInputReport::EMPTY
        };

        let reports = vec![
            create_touch_input_report(vec![first_contact], event_time_i64),
            create_touch_input_report(vec![second_contact], event_time_i64),
        ];

        let expected_events = vec![
            create_touch_event(
                hashmap! {
                    fidl_ui_input::PointerEventPhase::Add
                        => vec![create_touch_contact(TOUCH_ID, first)],
                    fidl_ui_input::PointerEventPhase::Down
                        => vec![create_touch_contact(TOUCH_ID, first)],
                },
                event_time_u64,
                &descriptor,
            ),
            create_touch_event(
                hashmap! {
                    fidl_ui_input::PointerEventPhase::Move
                        => vec![create_touch_contact(TOUCH_ID, second)],
                },
                event_time_u64,
                &descriptor,
            ),
        ];

        assert_input_report_sequence_generates_events!(
            input_reports: reports,
            expected_events: expected_events,
            device_descriptor: descriptor,
            device_type: TouchBinding,
        );
    }

    #[fasync::run_singlethreaded(test)]
    async fn sent_event_has_trace_id() {
        let previous_report_time = fuchsia_zircon::Time::get_monotonic().into_nanos();
        let previous_report = create_touch_input_report(vec![], previous_report_time);

        let report_time = fuchsia_zircon::Time::get_monotonic().into_nanos();
        let contact = fidl_fuchsia_input_report::ContactInputReport {
            contact_id: Some(222),
            position_x: Some(333),
            position_y: Some(444),
            ..fidl_fuchsia_input_report::ContactInputReport::EMPTY
        };
        let report = create_touch_input_report(vec![contact], report_time);

        let descriptor = input_device::InputDeviceDescriptor::Touch(TouchDeviceDescriptor {
            device_id: 1,
            contacts: vec![],
        });
        let (mut event_sender, mut event_receiver) = futures::channel::mpsc::channel(1);
        let _: Option<InputReport> = TouchBinding::process_reports(
            report,
            Some(previous_report),
            &descriptor,
            &mut event_sender,
        );
        assert_matches!(event_receiver.try_next(), Ok(Some(InputEvent { trace_id: Some(_), .. })));
    }

    #[test_case(true, None, TouchDeviceType::TouchScreen; "touch screen")]
    #[test_case(false, None, TouchDeviceType::TouchScreen; "no mouse descriptor, no touch_input_mode")]
    #[test_case(true, Some(fidl_input_report::TouchConfigurationInputMode::MouseCollection), TouchDeviceType::WindowsPrecisionTouchpad; "touchpad in mouse mode")]
    #[test_case(true, Some(fidl_input_report::TouchConfigurationInputMode::WindowsPrecisionTouchpadCollection), TouchDeviceType::WindowsPrecisionTouchpad; "touchpad in touchpad mode")]
    #[fasync::run_singlethreaded(test)]
    async fn windows_precision_touchpad(
        has_mouse_descriptor: bool,
        touch_input_mode: Option<fidl_input_report::TouchConfigurationInputMode>,
        expect_touch_device_type: TouchDeviceType,
    ) {
        let input_device_proxy = spawn_stream_handler(move |input_device_request| async move {
            match input_device_request {
                fidl_input_report::InputDeviceRequest::GetDescriptor { responder } => {
                    let _ = responder.send(fidl_input_report::DeviceDescriptor {
                        mouse: match has_mouse_descriptor {
                            true => Some(fidl_input_report::MouseDescriptor {
                                input: Some(fidl_input_report::MouseInputDescriptor {
                                    movement_x: None,
                                    movement_y: None,
                                    position_x: None,
                                    position_y: None,
                                    scroll_v: None,
                                    scroll_h: None,
                                    buttons: None,
                                    ..fidl_input_report::MouseInputDescriptor::EMPTY
                                }),
                                ..fidl_input_report::MouseDescriptor::EMPTY
                            }),
                            false => None,
                        },
                        touch: Some(fidl_input_report::TouchDescriptor {
                            input: Some(fidl_input_report::TouchInputDescriptor {
                                contacts: Some(vec![fidl_input_report::ContactInputDescriptor {
                                    position_x: Some(fidl_input_report::Axis {
                                        range: fidl_input_report::Range { min: 1, max: 2 },
                                        unit: fidl_input_report::Unit {
                                            type_: fidl_input_report::UnitType::None,
                                            exponent: 0,
                                        },
                                    }),
                                    position_y: Some(fidl_input_report::Axis {
                                        range: fidl_input_report::Range { min: 2, max: 3 },
                                        unit: fidl_input_report::Unit {
                                            type_: fidl_input_report::UnitType::Other,
                                            exponent: 100000,
                                        },
                                    }),
                                    pressure: Some(fidl_input_report::Axis {
                                        range: fidl_input_report::Range { min: 3, max: 4 },
                                        unit: fidl_input_report::Unit {
                                            type_: fidl_input_report::UnitType::Grams,
                                            exponent: -991,
                                        },
                                    }),
                                    contact_width: Some(fidl_input_report::Axis {
                                        range: fidl_input_report::Range { min: 5, max: 6 },
                                        unit: fidl_input_report::Unit {
                                            type_:
                                                fidl_input_report::UnitType::EnglishAngularVelocity,
                                            exponent: 123,
                                        },
                                    }),
                                    contact_height: Some(fidl_input_report::Axis {
                                        range: fidl_input_report::Range { min: 7, max: 8 },
                                        unit: fidl_input_report::Unit {
                                            type_: fidl_input_report::UnitType::Pascals,
                                            exponent: 100,
                                        },
                                    }),
                                    ..fidl_input_report::ContactInputDescriptor::EMPTY
                                }]),
                                ..fidl_input_report::TouchInputDescriptor::EMPTY
                            }),
                            ..fidl_input_report::TouchDescriptor::EMPTY
                        }),
                        ..fidl_input_report::DeviceDescriptor::EMPTY
                    });
                }
                fidl_input_report::InputDeviceRequest::GetFeatureReport { responder } => {
                    let _ = responder.send(&mut Ok(fidl_input_report::FeatureReport {
                        touch: Some(fidl_input_report::TouchFeatureReport {
                            input_mode: touch_input_mode,
                            ..fidl_input_report::TouchFeatureReport::EMPTY
                        }),
                        ..fidl_input_report::FeatureReport::EMPTY
                    }));
                }
                _ => panic!("InputDevice handler received an unexpected request"),
            }
        })
        .unwrap();

        let (device_event_sender, _) =
            futures::channel::mpsc::channel(input_device::INPUT_EVENT_BUFFER_SIZE);

        let binding = TouchBinding::new(input_device_proxy, 0, device_event_sender).await.unwrap();
        pretty_assertions::assert_eq!(binding._touch_device_type, expect_touch_device_type);
    }
}
