// Copyright 2021 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.

//! Implements dead key handling.
//!
//! Dead key is a character composition approach where an accented character,
//! typically from a Western European alphabet, is composed by actuating two
//! keys on the keyboard:
//!
//! 1. A "dead key" which determines which diacritic is to be placed on the
//!    character, and which produces no immediate output; and
//! 2. The character onto which the diacritic is to be placed.
//!
//! The resulting two successive key actuations produce an effect of single
//! accented character being emitted.
//!
//! The dead key handler relies on keymap already having been applied, and the
//! use of key meanings.
//!
//! This means that the dead key handler must be added to the input pipeline
//! after the keymap handler in the input pipeline.
//!
//! The dead key handler can delay or modify the key meanings, but it never delays nor
//! modifies key events.  This ensures that clients which require key events see the
//! key events as they come in.  The key meanings may be delayed because of the delayed
//! effect of composition.
//!
//! The state machine of the dead key handler is watching for dead key and "live" key
//! combinations, and handles all their possible interleaving. The event sequences
//! vary from the "obvious" ones such as "dead key press and release followed
//! by a live key press and release", to not so obvious ones such as: "dead key
//! press and hold, shift press, live key press and hold followed by another
//! live key press, followed by arbitrary sequence of key releases".
//!
//! See the documentation for [Handler] for some more detail.

use crate::input_device::{
    Handled, InputDeviceDescriptor, InputDeviceEvent, InputEvent, UnhandledInputEvent,
};
use crate::input_handler::UnhandledInputHandler;
use crate::keyboard_binding::KeyboardEvent;
use async_trait::async_trait;
use core::fmt;
use fidl_fuchsia_ui_input3::{KeyEventType, KeyMeaning};
use fuchsia_syslog::fx_log_debug;
use fuchsia_zircon as zx;
use rust_icu_sys as usys;
use rust_icu_unorm2 as unorm;
use std::cell::RefCell;
use std::rc::Rc;

// There probably is a more general method of determining whether the characters
// are combining characters. But somehow it escapes me now.
const GRAVE: u32 = 0x300;
const ACUTE: u32 = 0x301;
const CIRCUMFLEX: u32 = 0x302;
const TILDE: u32 = 0x303;

/// Returns true if `c` is one of the dead keys we support.
///
/// This should likely be some ICU library function, but I'm not sure which one.
fn is_dead_key(c: u32) -> bool {
    match c {
        GRAVE | ACUTE | CIRCUMFLEX | TILDE => true,
        _ => false,
    }
}

/// Removes the combining effect from a combining code point, leaving only
/// the diacritic.
///
/// This should likely be some ICU library function, but I'm not sure which one.
fn remove_combination(c: u32) -> u32 {
    match c {
        GRAVE => '`' as u32,
        ACUTE => '\'' as u32,
        CIRCUMFLEX => '^' as u32,
        TILDE => '~' as u32,
        _ => c,
    }
}

/// StoredEvent is an InputEvent which is known to be a keyboard event.
#[derive(Debug, Clone)]
struct StoredEvent {
    event: KeyboardEvent,
    device_descriptor: InputDeviceDescriptor,
    event_time: zx::Time,
}

impl fmt::Display for StoredEvent {
    // Implement a compact [Display], as the device descriptor is not
    // normally very interesting to see.
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "event: {:?}, event_time: {:?}", &self.event, &self.event_time)
    }
}

impl Into<InputEvent> for StoredEvent {
    /// Converts [StoredEvent] into [InputEvent].
    fn into(self) -> InputEvent {
        InputEvent {
            device_event: InputDeviceEvent::Keyboard(self.event),
            device_descriptor: self.device_descriptor,
            event_time: self.event_time,
            handled: Handled::No,
            trace_id: None,
        }
    }
}

impl Into<Vec<InputEvent>> for StoredEvent {
    fn into(self) -> Vec<InputEvent> {
        vec![self.into()]
    }
}

/// Whether a [StoredEvent] corresponds to a live key or a dead key.
enum Liveness {
    /// The key is dead.
    Dead,
    /// The key is live.
    Live,
}

/// Whether two events are the same or different by key.
enum Sameness {
    /// Two events are the same by key.
    Same,
    /// Two events are different.
    Other,
}

impl StoredEvent {
    /// Repackages self into a new [StoredEvent], with `event` replaced as supplied.
    fn into_with_event(self, event: KeyboardEvent) -> Self {
        StoredEvent {
            event,
            device_descriptor: self.device_descriptor,
            event_time: self.event_time,
        }
    }

    /// Returns the code point contained in this [StoredEvent].
    fn code_point(&self) -> u32 {
        match self.event.get_key_meaning() {
            Some(KeyMeaning::Codepoint(c)) => c,
            _ => panic!("programming error: requested code point for an event that has none"),
        }
    }

    /// Modifies this [StoredEvent] to contain a new code point instead of whatever was there.
    fn into_with_code_point(self, code_point: u32) -> Self {
        let new_event =
            self.event.clone().into_with_key_meaning(Some(KeyMeaning::Codepoint(code_point)));
        self.into_with_event(new_event)
    }

    /// Returns true if [StoredEvent] contains a valid code point.
    fn is_code_point(&self) -> bool {
        match self.event.get_key_meaning() {
            // Some nonprintable keys have the code point value set to 0.
            Some(KeyMeaning::Codepoint(c)) => c != 0,
            _ => false,
        }
    }

    /// Returns whether the key is a dead key or not.  The return value is an enum
    /// to make the state machine match arms more readable.
    fn key_liveness(&self) -> Liveness {
        match self.event.get_key_meaning() {
            Some(KeyMeaning::Codepoint(c)) if is_dead_key(c) => Liveness::Dead,
            _ => Liveness::Live,
        }
    }

    /// Returns the key event type (pressed, released, or something else)
    fn e_type(&self) -> KeyEventType {
        self.event.get_event_type_folded()
    }

    /// Returns a new [StoredEvent] based on `Self`, but with the combining effect removed.
    fn into_base_character(self) -> Self {
        let key_meaning = self.event.get_key_meaning();
        match key_meaning {
            Some(KeyMeaning::Codepoint(c)) => {
                let new_event = self
                    .event
                    .clone()
                    .into_with_key_meaning(Some(KeyMeaning::Codepoint(remove_combination(c))));
                self.into_with_event(new_event)
            }
            _ => self,
        }
    }

    /// Returns a new [StoredEvent], but with key meaning removed.
    fn remove_key_meaning(self) -> Self {
        let mut event = self.event.clone();
        // A zero code point means a KeyEvent for which its edit effect should
        // be ignored. In contrast, an event with an unset code point has by
        // definition the same effect as if the US QWERTY keymap were applied.
        // See discussion at:
        // https://groups.google.com/a/fuchsia.dev/g/ui-input-dev/c/ITYKvbJS6_o/m/8kK0DRccDAAJ
        event = event.into_with_key_meaning(Some(KeyMeaning::Codepoint(0)));
        self.into_with_event(event)
    }

    /// Returns whether the two keys `this` and `that` are in fact the same key
    /// as per the USB HID usage reported.  The return value is an enum to make
    /// the state machine match arms more readable.
    fn key_sameness(this: &StoredEvent, that: &StoredEvent) -> Sameness {
        match this.event.get_key() == that.event.get_key() {
            true => Sameness::Same,
            false => Sameness::Other,
        }
    }
}

/// State contains the current observed state of the dead key state machine.
///
/// The dead key composition is started by observing a key press that amounts
/// to a dead key.  The first non-dead key that gets actuated thereafter becomes
/// the "live" key that we will attempt to add a diacritic to.  When such a live
/// key is actuated, we will emit a key meaning equivalent to producing an
/// accented character.
///
/// A complication here is that composition can unfold in any number of ways.
/// The user could press and release the dead key, then press and release
/// the live key.  The user could, also, press and hold the dead key, then
/// press any number of live or dead keys in an arbitrary order.
///
/// Another complication is that the user could press the dead key twice, which
/// should also be handled correctly. In this case, "correct" handling implies
/// emitting the dead key as an accented character.  Similarly, two different
/// dead keys pressed in succession are handled by (1) emitting the first as
/// an accented character, and restarting composition with the second. It is
/// worth noting that the key press and key release events could be arbitrarily
/// interleaved for the two dead keys, and that should be handled correctly too.
///
/// A third complication is that, while all the composition is taking place,
/// the pipeline must emit the `KeyEvent`s consistent with the key event protocol,
/// but keep key meanings suppressed until the time that the key meanings have
/// been resolved by the combination.
///
/// The elements of state are as follows:
///
///   * Did we see a dead key press event? (bit `a`)
///   * Did we see a dead key release event? (bit `b`)
///   * Did we see a live key press event? (bit `c`)
///   * Did we see a live key release event? (bit `d`)
///
/// Almost any variation of the above elements is possible and allowed.  Even
/// the states that ostensibly shouldn't be possible (e.g. observed a release
/// event before a press) should be accounted for in order to implement
/// self-correcting behavior if needed.  The [State] enum below encodes each
/// state as a name `Sdcba`, where each of `a..d` are booleans, encoded
/// as characters `0` and `1` as conventional. So for example, `S0101`
/// is a state where we observed a dead key press event, and a live key press
/// event.  I made an experiment where I tried to use more illustrative state
/// names, but the number of variations didn't make the resulting names any more
/// meaningful compared to the current state name encoding scheme. So compact
/// naming it is.
#[derive(Debug, Clone)]
enum State {
    /// We have yet to see a key to act on.
    S0000,

    /// We saw an actuation of a dead key.
    S0001 { dead_key_down: StoredEvent },

    /// A dead key was pressed and released.
    S0011 { dead_key_down: StoredEvent, dead_key_up: StoredEvent },

    /// A dead key was pressed and released, followed by a live key press.
    S0111 { dead_key_down: StoredEvent, dead_key_up: StoredEvent, live_key_down: StoredEvent },

    /// A dead key was pressed, followed by a live key press.
    S0101 { dead_key_down: StoredEvent, live_key_down: StoredEvent },

    /// A dead key was pressed, then a live key was pressed and released.
    S1101 { dead_key_down: StoredEvent },
}

#[derive(Debug)]
pub struct Handler {
    /// Tracks the current state of the dead key composition.
    state: RefCell<State>,

    /// The unicode normalizer used for composition.
    normalizer: unorm::UNormalizer,

    /// This handler requires ICU data to be live. This is ensured by holding
    /// a reference to an ICU data loader.
    _data: icu_data::Loader,
}

/// This trait implementation allows the [Handler] to be hooked up into the input
/// pipeline.
#[async_trait(?Send)]
impl UnhandledInputHandler for Handler {
    async fn handle_unhandled_input_event(
        self: Rc<Self>,
        unhandled_input_event: UnhandledInputEvent,
    ) -> Vec<InputEvent> {
        self.handle_unhandled_input_event_internal(unhandled_input_event)
    }
}

impl Handler {
    /// Creates a new instance of the dead keys handler.
    pub fn new(icu_data: icu_data::Loader) -> Rc<Self> {
        let handler = Handler {
            state: RefCell::new(State::S0000),
            // The NFC normalizer performs the needed composition and is not
            // lossy.
            normalizer: unorm::UNormalizer::new_nfc().unwrap(),
            _data: icu_data,
        };
        Rc::new(handler)
    }

    fn handle_unhandled_input_event_internal(
        self: Rc<Self>,
        unhandled_input_event: UnhandledInputEvent,
    ) -> Vec<InputEvent> {
        match unhandled_input_event {
            UnhandledInputEvent {
                device_event: InputDeviceEvent::Keyboard(event),
                device_descriptor,
                event_time,
                trace_id: _,
            } => {
                let event = StoredEvent { event, device_descriptor, event_time };
                // Separated into two statements to ensure the logs are not truncated.
                fx_log_debug!("state: {:?}", self.state.borrow());
                fx_log_debug!("event: {}", &event);
                let result = self.process_keyboard_event(event);
                fx_log_debug!("result: {:?}", &result);
                result
            }

            // Pass other events unchanged.
            _ => vec![InputEvent::from(unhandled_input_event)],
        }
    }

    /// Sets the internal handler state to `new_state`.
    fn set_state(self: &Rc<Self>, new_state: State) {
        *(self.state.borrow_mut()) = new_state;
    }

    /// Attaches a key meaning to each passing keyboard event.
    ///
    /// Underlying this function is a state machine which registers the flow of dead and live keys
    /// after each reported event, and modifies the input event stream accordingly.  For example,
    /// a sequence of events where a dead key is pressed and released, followed by a live key
    /// press and release, results in a composed character being emitted.  The state machine
    /// takese care of this sequence, but also of other less obvious sequences and their effects.
    fn process_keyboard_event(self: &Rc<Self>, event: StoredEvent) -> Vec<InputEvent> {
        if !event.is_code_point() {
            // Pass through any non-codepoint events.
            return event.into();
        }
        let old_state = self.state.borrow().clone();
        match old_state {
            // We are waiting for the composition to begin.
            State::S0000 => match (event.key_liveness(), event.e_type()) {
                // A dead key press starts composition.  We advance to the next
                // state machine state, and eliminate any key meaning from the
                // key event, since we anticipate its use in composition.
                (Liveness::Dead, KeyEventType::Pressed) => {
                    self.set_state(State::S0001 { dead_key_down: event.clone() });
                    event.remove_key_meaning().into()
                }

                // A dead key release while we're waiting for a dead key press,
                // this is probably a remnant of an earlier double press, remove the
                // combining from it and forward.  Keep waiting for composition
                // to begin.
                (Liveness::Dead, KeyEventType::Released) => event.into_base_character().into(),

                // Any other events can be forwarded unmodified.
                _ => event.into(),
            },

            // We have seen a dead key press, but not release.
            State::S0001 { dead_key_down } => {
                match (
                    event.key_liveness(),
                    StoredEvent::key_sameness(&event, &dead_key_down),
                    event.e_type(),
                ) {
                    // The same dead key that was pressed the other time was released.
                    // Emit a stripped version, and start waiting for a live key.
                    (Liveness::Dead, Sameness::Same, KeyEventType::Released) => {
                        self.set_state(State::S0011 { dead_key_down, dead_key_up: event.clone() });
                        event.remove_key_meaning().into()
                    }

                    // Another dead key was released at this point.  Since
                    // we can not start a new combination here, we must forward
                    // it with meaning stripped.
                    (Liveness::Dead, Sameness::Other, KeyEventType::Released) => {
                        event.remove_key_meaning().into()
                    }

                    // The same dead key was pressed again, while we have seen
                    // it pressed before.  This can happen when autorepeat kicks
                    // in.  We treat this the same as two successive actuations
                    // i.e. we send a stripped version of the character, and
                    // go back to waiting.
                    (Liveness::Dead, Sameness::Same, KeyEventType::Pressed) => {
                        self.set_state(State::S0000);
                        event.into_base_character().into()
                    }

                    // A different dead key was pressed.  This stops the ongoing
                    // composition, and starts a new one with a new dead key.  However,
                    // what we emit is a bit subtle: we emit a key press event
                    // for the *new* key, but with a key meaning of the stripped
                    // version of the current key.
                    (Liveness::Dead, Sameness::Other, KeyEventType::Pressed) => {
                        let current_removed = dead_key_down.clone().into_base_character();
                        self.set_state(State::S0001 { dead_key_down: event.clone() });
                        event.into_with_code_point(current_removed.code_point()).into()
                    }

                    // A live key was pressed while the dead key is held down. Yay!
                    //
                    // Compose and ship out the live key with attached new meaning.
                    //
                    // A very similar piece of code happens in the state `State::S0011`,
                    // except we get there through a different sequence of events.
                    // Please refer to that code for the details about composition.
                    (Liveness::Live, _, KeyEventType::Pressed) => {
                        let maybe_composed = self.normalizer.compose_pair(
                            event.code_point() as usys::UChar32,
                            dead_key_down.code_point() as usys::UChar32,
                        );

                        if maybe_composed >= 0 {
                            // Composition was a success.
                            let composed_event = event.into_with_code_point(maybe_composed as u32);
                            self.set_state(State::S0101 {
                                dead_key_down,
                                live_key_down: composed_event.clone(),
                            });
                            return composed_event.into();
                        } else {
                            // FAIL!
                            self.set_state(State::S0101 {
                                dead_key_down,
                                live_key_down: event.clone(),
                            });
                            return event.into();
                        }
                    }
                    // All other key events are forwarded unmodified.
                    _ => event.into(),
                }
            }

            // The dead key was pressed and released, the first live key that
            // gets pressed after that now will be used for the composition.
            State::S0011 { dead_key_down, dead_key_up } => {
                match (event.key_liveness(), event.e_type()) {
                    // We observed a dead key actuation.
                    (Liveness::Dead, KeyEventType::Pressed) => {
                        match StoredEvent::key_sameness(&dead_key_down, &event) {
                            // The user pressed the same dead key again.  Let's "compose" it by
                            // stripping its diacritic and making that a compose key.
                            Sameness::Same => {
                                let event = event.into_base_character();
                                self.set_state(State::S0111 {
                                    dead_key_down,
                                    dead_key_up,
                                    live_key_down: event.clone(),
                                });
                                event.into()
                            }
                            // The user pressed a different dead key. It would have been nice
                            // to start a new composition, but we can not express that with the
                            // KeyEvent API, since that would require emitting spurious press and
                            // release key events for the dead key press and release.
                            //
                            // Instead, forward the key unmodified and cancel
                            // the composition.  We may revisit this if the KeyEvent API is
                            // changed to allow decoupling key events from key meanings.
                            Sameness::Other => {
                                self.set_state(State::S0000);
                                event.into_base_character().into()
                            }
                        }
                    }

                    // We observed a dead key release.  This is likely a dead key
                    // from the *previous* composition attempt.  Nothing to do here,
                    // except forward it stripped of key meaning.
                    (Liveness::Dead, KeyEventType::Released) => event.remove_key_meaning().into(),

                    // Oh, frabjous day! Someone pressed a live key that may be
                    // possible to combine!  Let's try it out!  If composition is
                    // a success, emit the current key with the meaning set to
                    // the composed character.
                    (Liveness::Live, KeyEventType::Pressed) => {
                        let maybe_composed = self.normalizer.compose_pair(
                            event.code_point() as usys::UChar32,
                            dead_key_down.code_point() as usys::UChar32,
                        );

                        if maybe_composed >= 0 {
                            // Composition was a success.
                            // Emit the composed event, remember it also when
                            // transitioning to S0111, so we can recover the key meaning
                            // when the live key is released.
                            let composed_event = event.into_with_code_point(maybe_composed as u32);
                            self.set_state(State::S0111 {
                                dead_key_down,
                                dead_key_up,
                                live_key_down: composed_event.clone(),
                            });
                            return composed_event.into();
                        } else {
                            fx_log_debug!("compose failed for: {}\n", &event);
                            // FAIL!
                            // Composition failed, what now?  We would need to
                            // emit TWO characters - one for the now-defunct
                            // dead key, and another for the current live key.
                            // But this is not possible, since we may not emit
                            // more combining key events, but must always emit
                            // both the key and the key meaning since that is
                            // how our protocol works.  Well, we reached the
                            // limit of what key event composition may do, so
                            // let's simply agree to emit the current event
                            // unmodified and forget we had the dead key.
                            self.set_state(State::S0111 {
                                dead_key_down,
                                dead_key_up,
                                live_key_down: event.clone(),
                            });
                            return event.into();
                        }
                    }

                    // All other key events are forwarded unmodified.
                    _ => event.into(),
                }
            }

            // We already combined the live key with the dead key, and are
            // now waiting for the live key to be released.
            State::S0111 { dead_key_down, dead_key_up, live_key_down } => {
                match (
                    event.key_liveness(),
                    // Here we compare the current key with the live key down,
                    // unlike in prior states.
                    StoredEvent::key_sameness(&event, &live_key_down),
                    event.e_type(),
                ) {
                    // This is what we've been waiting for: the live key is now
                    // lifted.  Emit the live key release using the same code point
                    // as we used when the key went down, and we're done.
                    (Liveness::Live, Sameness::Same, KeyEventType::Released) => {
                        self.set_state(State::S0000);
                        event.into_with_code_point(live_key_down.code_point()).into()
                    }

                    // A second press of the live key we're combining.  This is
                    // probably a consequence of autorepeat.  The effect should
                    // be to complete the composition and continue emitting the
                    // "base" key meaning for any further repeats; but also
                    // continue waiting for a key release.
                    (Liveness::Live, Sameness::Same, KeyEventType::Pressed) => {
                        let base_codepoint = event.code_point();
                        let combined_event =
                            event.clone().into_with_code_point(live_key_down.code_point());
                        // We emit a combined key, but further repeats will use the
                        // base code point and not combine.
                        self.set_state(State::S0111 {
                            dead_key_down,
                            dead_key_up,
                            live_key_down: event.into_with_code_point(base_codepoint),
                        });
                        combined_event.into()
                    }

                    // If another live key event comes in, just forward it, and
                    // continue waiting for the last live key release.
                    (Liveness::Live, Sameness::Other, _) => event.into(),

                    // Another dead key has been pressed in addition to what
                    // had been pressed before. So now, we are waiting for the
                    // user to release the live key we already composed, but the
                    // user is again pressing a compose key instead.
                    //
                    // Ideally, we'd want to start new composition with the
                    // new dead key.  But, there's still the issue with the
                    // live key that is still being pressed: when it is eventually
                    // released, we want to have it have exactly the same key
                    // meaning as what we emitted for when it was pressed.  But,
                    // that may happen arbitrarily late afterwards, and we'd
                    // prefer not to keep any composition state for that long.
                    //
                    // That suggests that we must not honor this new dead key
                    // as composition.  But, also, we must not drop the key
                    // event on the floor, since the clients that read key
                    // events must receive it.  So, we just *turn* off
                    // the combining effect on this key, forward it like that,
                    // and continue waiting for the key release.
                    (Liveness::Dead, _, KeyEventType::Pressed) => event.remove_key_meaning().into(),

                    (Liveness::Dead, _, KeyEventType::Released) => {
                        match StoredEvent::key_sameness(&event, &live_key_down) {
                            // Special: if the released key a dead key and the same as the
                            // "live" composing key, then we're seeing a release of a doubly-
                            // pressed dead key.  This one needs to be emitted as a diacritic.
                            Sameness::Same => {
                                self.set_state(State::S0000);
                                event.into_base_character().into()
                            }

                            // All other dead keys are forwarded with stripped key meanings.
                            // We have no way to handle them further.
                            Sameness::Other => event.remove_key_meaning().into(),
                        }
                    }

                    // Forward any other events unmodified.
                    _ => event.into(),
                }
            }

            // The user pressed and is holding the dead key; and pressed and
            // is holding a live key.
            State::S0101 { dead_key_down, live_key_down } => {
                match (event.key_liveness(), event.e_type()) {
                    // The same dead key we're already holding is pressed.  Just forward
                    // the key event, but not meaning.
                    (Liveness::Dead, KeyEventType::Pressed) => event.remove_key_meaning().into(),

                    (Liveness::Dead, KeyEventType::Released) => {
                        // The dead key that we are using for combining is released.
                        // Emit its release event without a key meaning and go to a
                        // state that expects a release of the live key.
                        match StoredEvent::key_sameness(&dead_key_down, &event) {
                            Sameness::Same => {
                                self.set_state(State::S0111 {
                                    dead_key_down,
                                    dead_key_up: event.clone(),
                                    live_key_down,
                                });
                                event.remove_key_meaning().into()
                            }

                            // Other dead key is released.  Remove its key meaning, but forward.
                            Sameness::Other => event.remove_key_meaning().into(),
                        }
                    }
                    (Liveness::Live, KeyEventType::Pressed) => {
                        match StoredEvent::key_sameness(&live_key_down, &event) {
                            // The currently pressed live key is pressed again.
                            // This is autorepeat.  We emit one composed key, but any
                            // further emitted keys will not compose.  This
                            // should be similar to `State::S0111`, except the
                            // transition is back to *this* state.
                            Sameness::Same => {
                                let base_codepoint = event.code_point();
                                let combined_event =
                                    event.clone().into_with_code_point(live_key_down.code_point());
                                self.set_state(State::S0101 {
                                    dead_key_down,
                                    live_key_down: event.into_with_code_point(base_codepoint),
                                });
                                combined_event.into()
                            }
                            Sameness::Other => event.into(),
                        }
                    }
                    (Liveness::Live, KeyEventType::Released) => {
                        match StoredEvent::key_sameness(&live_key_down, &event) {
                            Sameness::Same => {
                                self.set_state(State::S1101 { dead_key_down });
                                event.into_with_code_point(live_key_down.code_point()).into()
                            }

                            // Any other release just gets forwarded.
                            Sameness::Other => event.into(),
                        }
                    }

                    // Forward any other events unmodified
                    _ => event.into(),
                }
            }

            // The dead key is still actuated, but we already sent out the
            // combined versions of the live key.
            State::S1101 { dead_key_down } => {
                match (event.key_liveness(), event.e_type()) {
                    (Liveness::Dead, KeyEventType::Pressed) => {
                        // Two possible cases here, but the outcome is the
                        // same:
                        //
                        // The same dead key is pressed again.  Let's not
                        // do any more compositions here.
                        //
                        // A different dead key has been pressed.  We can
                        // not start a new composition while we have not
                        // closed out the current composition.  For this
                        // reason we ignore the other key.
                        //
                        // A real compositioning API would perhaps allow us
                        // to stack compositions on top of each other, but
                        // we will require any such consumers to go talk to
                        // the text editing API instead.
                        event.remove_key_meaning().into()
                    }

                    (Liveness::Dead, KeyEventType::Released) => {
                        match StoredEvent::key_sameness(&dead_key_down, &event) {
                            // The dead key is released, the composition is
                            // done, let's close up shop.
                            Sameness::Same => {
                                self.set_state(State::S0000);
                                event.remove_key_meaning().into()
                            }
                            // A dead key was released, but not the one that we
                            // are combining by.  Forward with the combining
                            // effect stripped.
                            Sameness::Other => event.remove_key_meaning().into(),
                        }
                    }

                    // Any additional live keys, no matter if they are the same
                    // as the one currently being composed, will *not* be composed,
                    // we forward them unmodified as we wait to close off this
                    // composition.
                    //
                    // Forward any other events unmodified.
                    _ => event.into(),
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::testing_utilities;
    use fidl_fuchsia_input::Key;
    use fidl_fuchsia_ui_input3::{KeyEventType, KeyMeaning};
    use fuchsia_zircon as zx;
    use pretty_assertions::assert_eq;
    use std::convert::TryFrom as _;

    // Creates a new keyboard event for testing.
    fn new_event(
        key: Key,
        event_type: KeyEventType,
        key_meaning: Option<KeyMeaning>,
    ) -> UnhandledInputEvent {
        UnhandledInputEvent::try_from(testing_utilities::create_keyboard_event_with_handled(
            key,
            event_type,
            /*modifiers=*/ None,
            /*event_time*/ zx::Time::ZERO,
            &InputDeviceDescriptor::Fake,
            /*keymap=*/ None,
            key_meaning,
            /*handled=*/ Handled::No,
        ))
        .unwrap()
    }

    // Tests some common keyboard input use cases with dead keys actuation.
    #[test]
    fn test_input_processing() {
        // A zero codepoint is a way to let the consumers know that this key
        // event should have no effect on the edited text; even though its
        // key event may have other effects, such as moving the hero across
        // the screen in a game.
        const ZERO_CP: Option<KeyMeaning> = Some(KeyMeaning::Codepoint(0));

        #[derive(Debug)]
        struct TestCase {
            name: &'static str,
            // The sequence of input events at the input of the dead keys
            // handler.
            inputs: Vec<UnhandledInputEvent>,
            // The expected sequence of input events, after being transformed
            // by the dead keys handler.
            expected: Vec<UnhandledInputEvent>,
        }
        let tests: Vec<TestCase> = vec![
            TestCase {
                name: "passthrough",
                inputs: vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                ],
                expected: vec![
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "A circumflex - dead key first, then live key",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "A circumflex - dead key held all the way through composition",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                ],
            },
            TestCase {
                name: "A circumflex - dead key held until the live key was down",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "Combining character pressed twice - results in a single diacritic",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('^' as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('^' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "A circumflex - dead key spans live key",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                ],
            },
            TestCase {
                name: "Only the first key after the dead key actuation is composed",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::E,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('E' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::E,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('E' as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::E,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('E' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::E,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('E' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "Modifier keys are not affected",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(Key::LeftShift, KeyEventType::Pressed, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(Key::LeftShift, KeyEventType::Released, ZERO_CP),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(Key::LeftShift, KeyEventType::Pressed, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(Key::LeftShift, KeyEventType::Released, ZERO_CP),
                ],
            },
            TestCase {
                name: "Two dead keys in succession - no compose",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(GRAVE as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(GRAVE as u32)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('`' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('`' as u32)),
                    ),
                ],
            },
            TestCase {
                name: "Compose with capital letter",
                inputs: vec![
                    new_event(
                        Key::Key5,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::Key5,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(CIRCUMFLEX as u32)),
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(0)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('A' as u32)),
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(0)),
                    ),
                ],
                expected: vec![
                    new_event(Key::Key5, KeyEventType::Pressed, ZERO_CP),
                    new_event(Key::Key5, KeyEventType::Released, ZERO_CP),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint(0)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Pressed,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::A,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint('Â' as u32)),
                    ),
                    new_event(
                        Key::LeftShift,
                        KeyEventType::Released,
                        Some(KeyMeaning::Codepoint(0)),
                    ),
                ],
            },
        ];

        let loader = icu_data::Loader::new().unwrap();
        let handler = super::Handler::new(loader);
        for test in tests {
            let actuals: Vec<InputEvent> = test
                .inputs
                .into_iter()
                .map(|event| handler.clone().handle_unhandled_input_event_internal(event))
                .flatten()
                .collect();
            assert_eq!(
                test.expected.into_iter().map(InputEvent::from).collect::<Vec<_>>(),
                actuals,
                "in test: {}",
                test.name
            );
        }
    }
}
