// Copyright 2022 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, InputEvent};
use crate::keyboard_binding::{KeyboardDeviceDescriptor, KeyboardEvent};
use anyhow::{Context, Result};
use fidl_fuchsia_ui_input3::KeyEventType;
use fidl_fuchsia_ui_scenic as fscenic;
use fuchsia_async::{OnSignals, Task};
use fuchsia_syslog::{fx_log_debug, fx_log_info, fx_log_warn};
use fuchsia_zircon::{AsHandleRef, Duration, Signals, Status, Time};
use futures::{
    channel::mpsc::{self, UnboundedReceiver, UnboundedSender},
    select, StreamExt,
};
use keymaps::KeyState;
use lazy_static::lazy_static;
use std::{cell::RefCell, rc::Rc};

lazy_static! {
    // The signal value corresponding to the `DISPLAY_OWNED_SIGNAL`.  Same as zircon's signal
    // USER_0.
    static ref DISPLAY_OWNED: Signals = Signals::from_bits(fscenic::DISPLAY_OWNED_SIGNAL)
        .expect("static init should not fail")    ;

    // The signal value corresponding to the `DISPLAY_NOT_OWNED_SIGNAL`.  Same as zircon's signal
    // USER_1.
    static ref DISPLAY_UNOWNED: Signals = Signals::from_bits(fscenic::DISPLAY_NOT_OWNED_SIGNAL)
        .expect("static init should not fail")    ;

    // Any display-related signal.
    static ref ANY_DISPLAY_EVENT: Signals = *DISPLAY_OWNED | *DISPLAY_UNOWNED;
}

// Stores the last received ownership signals.
#[derive(Debug, Clone, PartialEq)]
struct Ownership {
    signals: Signals,
}

impl std::convert::From<Signals> for Ownership {
    fn from(signals: Signals) -> Self {
        Ownership { signals }
    }
}

impl Ownership {
    // Returns true if the display is currently indicated to be not owned by
    // Scenic.
    fn is_display_ownership_lost(&self) -> bool {
        self.signals.contains(*DISPLAY_UNOWNED)
    }

    // Returns the mask of the next signal to watch.
    //
    // Since the ownership alternates, so does the next signal to wait on.
    fn next_signal(&self) -> Signals {
        match self.is_display_ownership_lost() {
            true => *DISPLAY_OWNED,
            false => *DISPLAY_UNOWNED,
        }
    }

    /// Waits for the next signal change.
    ///
    /// If the display is owned, it will wait for display to become unowned.
    /// If the display is unowned, it will wait for the display to become owned.
    async fn wait_ownership_change<'a, T: AsHandleRef>(
        &self,
        event: &'a T,
    ) -> Result<Signals, Status> {
        OnSignals::new(event, self.next_signal()).await
    }
}

/// A handler that turns the input pipeline off or on based on whether
/// the Scenic owns the display.
///
/// This allows us to turn off keyboard processing when the user switches away
/// from the product (e.g. terminal) into virtual console.
///
/// See the `README.md` file in this crate for details.
pub struct DisplayOwnership {
    /// The current view of the display ownership.  It is mutated by the
    /// display ownership task when appropriate signals arrive.
    ownership: Rc<RefCell<Ownership>>,

    /// The registry of currently pressed keys.
    key_state: RefCell<KeyState>,

    /// The source of ownership change events for the main loop.
    display_ownership_change_receiver: RefCell<UnboundedReceiver<Ownership>>,

    /// A background task that watches for display ownership changes.  We keep
    /// it alive to ensure that it keeps running.
    _display_ownership_task: Task<()>,

    /// The event processing loop will do an `unbounded_send(())` on this
    /// channel once at the end of each loop pass, in test configurations only.
    /// The test fixture uses this channel to execute test fixture in
    /// lock-step with the event processing loop for test cases where the
    /// precise event sequencing is relevant.
    #[cfg(test)]
    loop_done: RefCell<Option<UnboundedSender<()>>>,
}

impl DisplayOwnership {
    /// Creates a new handler that watches `display_ownership_event` for events.
    ///
    /// The `display_ownership_event` is assumed to be an [Event] obtained from
    /// Scenic using `fuchsia.ui.scenic.Scenic/GetDisplayOwnershipEvent`.  There
    /// isn't really a way for this code to know here whether this is true or
    /// not, so implementor beware.
    pub fn new(display_ownership_event: impl AsHandleRef + 'static) -> Rc<Self> {
        DisplayOwnership::new_internal(display_ownership_event, None)
    }

    #[cfg(test)]
    pub fn new_for_test(
        display_ownership_event: impl AsHandleRef + 'static,
        loop_done: UnboundedSender<()>,
    ) -> Rc<Self> {
        DisplayOwnership::new_internal(display_ownership_event, Some(loop_done))
    }

    fn new_internal(
        display_ownership_event: impl AsHandleRef + 'static,
        _loop_done: Option<UnboundedSender<()>>,
    ) -> Rc<Self> {
        let initial_state = display_ownership_event
            // scenic guarantees that ANY_DISPLAY_EVENT is asserted. If it is
            // not, this will fail with a timeout error.
            .wait_handle(*ANY_DISPLAY_EVENT, Time::INFINITE_PAST)
            .expect("unable to set the initial display state");
        fx_log_debug!("setting initial display ownership to: {:?}", &initial_state);
        let initial_ownership: Ownership = initial_state.into();
        let ownership = Rc::new(RefCell::new(initial_ownership.clone()));

        let mut ownership_clone = initial_ownership.clone();
        let (ownership_sender, ownership_receiver) = mpsc::unbounded();
        let display_ownership_task = Task::local(async move {
            loop {
                let signals = ownership_clone.wait_ownership_change(&display_ownership_event).await;
                match signals {
                    Err(e) => {
                        fx_log_warn!("could not read display state: {:?}", e);
                        break;
                    }
                    Ok(signals) => {
                        fx_log_debug!("setting display ownership to: {:?}", &signals);
                        ownership_sender.unbounded_send(signals.into()).unwrap();
                        ownership_clone = signals.into();
                    }
                }
            }
            fx_log_warn!("display loop exiting and will no longer monitor display changes - this is not expected");
        });
        fx_log_info!("Display ownership handler installed");
        Rc::new(Self {
            ownership,
            key_state: RefCell::new(KeyState::new()),
            display_ownership_change_receiver: RefCell::new(ownership_receiver),
            _display_ownership_task: display_ownership_task,
            #[cfg(test)]
            loop_done: RefCell::new(_loop_done),
        })
    }

    /// Returns true if the display is currently *not* owned by Scenic.
    fn is_display_ownership_lost(&self) -> bool {
        self.ownership.borrow().is_display_ownership_lost()
    }

    /// Run this function in an executor to handle events.
    pub async fn handle_input_events(
        self: &Rc<Self>,
        mut input: UnboundedReceiver<InputEvent>,
        output: UnboundedSender<InputEvent>,
    ) -> Result<()> {
        loop {
            let mut ownership_source = self.display_ownership_change_receiver.borrow_mut();
            select! {
                // Display ownership changed.
                new_ownership = ownership_source.select_next_some() => {
                    let is_display_ownership_lost = new_ownership.is_display_ownership_lost();
                    // When the ownership is modified, float a set of cancel or sync
                    // events to scoop up stale keyboard state, treating it the same
                    // as loss of focus.
                    let event_type = match is_display_ownership_lost {
                        true => KeyEventType::Cancel,
                        false => KeyEventType::Sync,
                    };
                    let keys = self.key_state.borrow().get_set();
                    let mut event_time = Time::get_monotonic();
                    for key in keys.into_iter() {
                        let key_event = KeyboardEvent::new(key, event_type);
                        output.unbounded_send(into_input_event(key_event, event_time))
                            .context("unable to send display updates")?;
                        event_time = event_time + Duration::from_nanos(1);
                    }
                    *(self.ownership.borrow_mut()) = new_ownership;
                },

                // An input event arrived.
                event = input.select_next_some() => {
                    if event.is_handled() {
                        // Forward handled events unmodified.
                        output.unbounded_send(event).context("unable to send handled event")?;
                        continue;
                    }
                    match event.device_event {
                        input_device::InputDeviceEvent::Keyboard(ref event) => {
                            self.key_state.borrow_mut().update(event.get_event_type(), event.get_key());
                        },
                        _ => {},
                    }
                    let is_display_ownership_lost = self.is_display_ownership_lost();
                    output.unbounded_send(
                        input_device::InputEvent::from(event)
                            .into_handled_if(is_display_ownership_lost)
                    ).context("unable to send input event updates")?;
                },
            };
            #[cfg(test)]
            {
                self.loop_done.borrow_mut().as_ref().unwrap().unbounded_send(()).unwrap();
            }
        }
    }
}

fn empty_keyboard_device_descriptor() -> input_device::InputDeviceDescriptor {
    input_device::InputDeviceDescriptor::Keyboard(
        // Should descriptor be something sensible?
        KeyboardDeviceDescriptor { keys: vec![] },
    )
}

fn into_input_event(keyboard_event: KeyboardEvent, event_time: Time) -> input_device::InputEvent {
    input_device::InputEvent {
        device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event),
        device_descriptor: empty_keyboard_device_descriptor(),
        event_time,
        handled: input_device::Handled::No,
        trace_id: None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::input_device::InputEvent;
    use crate::testing_utilities::{create_fake_input_event, create_input_event};
    use fidl_fuchsia_input::Key;
    use fidl_fuchsia_ui_input3::KeyEventType;
    use fuchsia_async as fasync;
    use fuchsia_zircon::{EventPair, Peered, Time};
    use futures::channel::mpsc;
    use pretty_assertions::assert_eq;

    // Manages losing and regaining display, since manual management is error-prone:
    // if signal_peer does not change the signal state, the waiting process will block
    // forever, which makes tests run longer than needed.
    struct DisplayWrangler {
        event: EventPair,
        last: Signals,
    }

    impl DisplayWrangler {
        fn new(event: EventPair) -> Self {
            let mut instance = DisplayWrangler { event, last: *DISPLAY_OWNED };
            // Signal needs to be initialized before the handlers attempts to read it.
            // This is normally always the case in production.
            // Else, the `new_for_test` below will panic with a TIMEOUT error.
            instance.set_unowned();
            instance
        }

        fn set_unowned(&mut self) {
            assert!(self.last != *DISPLAY_UNOWNED, "display is already unowned");
            self.event.signal_peer(*DISPLAY_OWNED, *DISPLAY_UNOWNED).unwrap();
            self.last = *DISPLAY_UNOWNED;
        }

        fn set_owned(&mut self) {
            assert!(self.last != *DISPLAY_OWNED, "display is already owned");
            self.event.signal_peer(*DISPLAY_UNOWNED, *DISPLAY_OWNED).unwrap();
            self.last = *DISPLAY_OWNED;
        }
    }

    #[fuchsia::test]
    async fn display_ownership_change() {
        // handler_event is the event that the unit under test will examine for
        // display ownership changes.  test_event is used to set the appropriate
        // signals.
        let (test_event, handler_event) = EventPair::create().unwrap();

        // test_sender is used to pipe input events into the handler.
        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();

        // test_receiver is used to pipe input events out of the handler.
        let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();

        // The unit under test adds a () each time it completes one pass through
        // its event loop.  Use to ensure synchronization.
        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();

        // We use a wrapper to signal test_event correctly, since doing it wrong
        // by hand causes tests to hang, which isn't the best dev experience.
        let mut wrangler = DisplayWrangler::new(test_event);
        let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);

        let _task = fasync::Task::local(async move {
            handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
        });

        let fake_time = Time::from_nanos(42);

        // Go two full circles of signaling.

        // 1
        wrangler.set_owned();
        loop_done.next().await;
        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
        loop_done.next().await;

        // 2
        wrangler.set_unowned();
        loop_done.next().await;
        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
        loop_done.next().await;

        // 3
        wrangler.set_owned();
        loop_done.next().await;
        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
        loop_done.next().await;

        // 4
        wrangler.set_unowned();
        loop_done.next().await;
        test_sender.unbounded_send(create_fake_input_event(fake_time)).unwrap();
        loop_done.next().await;

        let actual: Vec<InputEvent> =
            test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;

        assert_eq!(
            actual,
            vec![
                // Event received while we owned the display.
                create_fake_input_event(fake_time),
                // Event received when we lost the display.
                create_fake_input_event(fake_time).into_handled(),
                // Display ownership regained.
                create_fake_input_event(fake_time),
                // Display ownership lost.
                create_fake_input_event(fake_time).into_handled(),
            ]
        );
    }

    fn new_keyboard_input_event(key: Key, event_type: KeyEventType) -> InputEvent {
        let fake_time = Time::from_nanos(42);
        create_input_event(
            KeyboardEvent::new(key, event_type),
            &input_device::InputDeviceDescriptor::Fake,
            fake_time,
            input_device::Handled::No,
        )
    }

    #[fuchsia::test]
    async fn basic_key_state_handling() {
        let (test_event, handler_event) = EventPair::create().unwrap();
        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
        let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
        let mut wrangler = DisplayWrangler::new(test_event);
        let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
        let _task = fasync::Task::local(async move {
            handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
        });

        let fake_time = Time::from_nanos(42);

        // Gain the display, and press a key.
        wrangler.set_owned();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
            .unwrap();
        loop_done.next().await;

        // Lose display.
        wrangler.set_unowned();
        loop_done.next().await;

        // Regain display
        wrangler.set_owned();
        loop_done.next().await;

        // Key event after regaining.
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
            .unwrap();
        loop_done.next().await;

        let actual: Vec<InputEvent> =
            test_receiver.take(4).map(|e| e.into_with_event_time(fake_time)).collect().await;

        assert_eq!(
            actual,
            vec![
                new_keyboard_input_event(Key::A, KeyEventType::Pressed),
                new_keyboard_input_event(Key::A, KeyEventType::Cancel)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::A, KeyEventType::Sync)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::A, KeyEventType::Released),
            ]
        );
    }

    #[fuchsia::test]
    async fn more_key_state_handling() {
        let (test_event, handler_event) = EventPair::create().unwrap();
        let (test_sender, handler_receiver) = mpsc::unbounded::<InputEvent>();
        let (handler_sender, test_receiver) = mpsc::unbounded::<InputEvent>();
        let (loop_done_sender, mut loop_done) = mpsc::unbounded::<()>();
        let mut wrangler = DisplayWrangler::new(test_event);
        let handler = DisplayOwnership::new_for_test(handler_event, loop_done_sender);
        let _task = fasync::Task::local(async move {
            handler.handle_input_events(handler_receiver, handler_sender).await.unwrap();
        });

        let fake_time = Time::from_nanos(42);

        wrangler.set_owned();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Pressed))
            .unwrap();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Pressed))
            .unwrap();
        loop_done.next().await;

        // Lose display, release a key, press a key.
        wrangler.set_unowned();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::B, KeyEventType::Released))
            .unwrap();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Pressed))
            .unwrap();
        loop_done.next().await;

        // Regain display
        wrangler.set_owned();
        loop_done.next().await;

        // Key event after regaining.
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::A, KeyEventType::Released))
            .unwrap();
        loop_done.next().await;
        test_sender
            .unbounded_send(new_keyboard_input_event(Key::C, KeyEventType::Released))
            .unwrap();
        loop_done.next().await;

        let actual: Vec<InputEvent> =
            test_receiver.take(10).map(|e| e.into_with_event_time(fake_time)).collect().await;

        assert_eq!(
            actual,
            vec![
                new_keyboard_input_event(Key::A, KeyEventType::Pressed),
                new_keyboard_input_event(Key::B, KeyEventType::Pressed),
                new_keyboard_input_event(Key::A, KeyEventType::Cancel)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::B, KeyEventType::Cancel)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::B, KeyEventType::Released).into_handled(),
                new_keyboard_input_event(Key::C, KeyEventType::Pressed).into_handled(),
                // The CANCEL and SYNC events are emitted in the sort ordering of the
                // `Key` enum values. Perhaps they should be emitted instead in the order
                // they have been received for SYNC, and in reverse order for CANCEL.
                new_keyboard_input_event(Key::A, KeyEventType::Sync)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::C, KeyEventType::Sync)
                    .into_with_device_descriptor(empty_keyboard_device_descriptor()),
                new_keyboard_input_event(Key::A, KeyEventType::Released),
                new_keyboard_input_event(Key::C, KeyEventType::Released),
            ]
        );
    }
}
