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

use crate::autorepeater;
use crate::input_device;
use crate::input_handler::UnhandledInputHandler;
use anyhow::{Context, Error, Result};
use async_trait::async_trait;
use fidl_fuchsia_input as finput;
use fidl_fuchsia_settings as fsettings;
use fuchsia_async as fasync;
use fuchsia_syslog::{fx_log_debug, fx_log_err};
use futures::{TryFutureExt, TryStreamExt};
use std::cell::RefCell;
use std::rc::Rc;

use async_utils::hanging_get::client::HangingGetStream;

/// The text settings handler instance. Refer to as `text_settings_handler::TextSettingsHandler`.
/// Its task is to decorate an input event with the keymap identifier.  The instance can
/// be freely cloned, each clone is thread-safely sharing data with others.
#[derive(Debug)]
pub struct TextSettingsHandler {
    /// Stores the currently active keymap identifier, if present.  Wrapped
    /// in an refcell as it can be changed out of band through
    /// `fuchsia.input.keymap.Configuration/SetLayout`.
    keymap_id: RefCell<Option<finput::KeymapId>>,

    /// Stores the currently active autorepeat settings.
    autorepeat_settings: RefCell<Option<autorepeater::Settings>>,
}

#[async_trait(?Send)]
impl UnhandledInputHandler for TextSettingsHandler {
    async fn handle_unhandled_input_event(
        self: Rc<Self>,
        unhandled_input_event: input_device::UnhandledInputEvent,
    ) -> Vec<input_device::InputEvent> {
        match unhandled_input_event {
            input_device::UnhandledInputEvent {
                device_event: input_device::InputDeviceEvent::Keyboard(mut event),
                device_descriptor,
                event_time,
                trace_id: _,
            } => {
                let keymap_id = self.get_keymap_name();
                fx_log_debug!(
                    "text_settings_handler::Instance::handle_unhandled_input_event: keymap_id = {:?}",
                    &keymap_id
                );
                event = event
                    .into_with_keymap(keymap_id)
                    .into_with_autorepeat_settings(self.get_autorepeat_settings());
                vec![input_device::InputEvent {
                    device_event: input_device::InputDeviceEvent::Keyboard(event),
                    device_descriptor,
                    event_time,
                    handled: input_device::Handled::No,
                    trace_id: None,
                }]
            }
            // Pass a non-keyboard event through.
            _ => vec![input_device::InputEvent::from(unhandled_input_event)],
        }
    }
}

impl TextSettingsHandler {
    /// Creates a new text settings handler instance.
    ///
    /// `initial_*` contain the desired initial values to be served.  Usually
    /// you want the defaults.
    pub fn new(
        initial_keymap: Option<finput::KeymapId>,
        initial_autorepeat: Option<autorepeater::Settings>,
    ) -> Rc<Self> {
        Rc::new(Self {
            keymap_id: RefCell::new(initial_keymap),
            autorepeat_settings: RefCell::new(initial_autorepeat),
        })
    }

    /// Processes requests for keymap change from `stream`.
    pub async fn process_keymap_configuration_from(
        self: &Rc<Self>,
        proxy: fsettings::KeyboardProxy,
    ) -> Result<(), Error> {
        let mut stream = HangingGetStream::new(proxy, fsettings::KeyboardProxy::watch);
        loop {
            match stream
                .try_next()
                .await
                .context("while waiting on fuchsia.settings.Keyboard/Watch")?
            {
                Some(fsettings::KeyboardSettings { keymap, autorepeat, .. }) => {
                    self.set_keymap_id(keymap);
                    self.set_autorepeat_settings(autorepeat.map(|e| e.into()));
                    fx_log_debug!("keymap ID set to: {:?}", self.get_keymap_id());
                }
                e => {
                    fx_log_err!("exiting - unexpected response: {:?}", &e);
                    break;
                }
            }
        }
        Ok(())
    }

    /// Starts reading events from the stream.  Does not block.
    pub fn serve(self: Rc<Self>, proxy: fsettings::KeyboardProxy) {
        fasync::Task::local(
            async move { self.process_keymap_configuration_from(proxy).await }
                .unwrap_or_else(|e: anyhow::Error| fx_log_err!("can't run: {:?}", e)),
        )
        .detach();
    }

    fn set_keymap_id(self: &Rc<Self>, keymap_id: Option<finput::KeymapId>) {
        *(self.keymap_id.borrow_mut()) = keymap_id;
    }

    fn set_autorepeat_settings(self: &Rc<Self>, autorepeat: Option<autorepeater::Settings>) {
        *(self.autorepeat_settings.borrow_mut()) = autorepeat.map(|s| s.into());
    }

    /// Gets the currently active keymap ID.
    pub fn get_keymap_id(&self) -> Option<finput::KeymapId> {
        self.keymap_id.borrow().clone()
    }

    /// Gets the currently active autorepeat settings.
    pub fn get_autorepeat_settings(&self) -> Option<autorepeater::Settings> {
        self.autorepeat_settings.borrow().clone()
    }

    fn get_keymap_name(&self) -> Option<String> {
        // Maybe instead just pass in the keymap ID directly?
        match *self.keymap_id.borrow() {
            Some(id) => match id {
                finput::KeymapId::FrAzerty => Some("FR_AZERTY".to_owned()),
                finput::KeymapId::UsDvorak => Some("US_DVORAK".to_owned()),
                finput::KeymapId::UsQwerty | finput::KeymapIdUnknown!() => {
                    Some("US_QWERTY".to_owned())
                }
            },
            None => Some("US_QWERTY".to_owned()),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::input_device;
    use crate::keyboard_binding;
    use crate::testing_utilities;
    use fidl_fuchsia_input;
    use fidl_fuchsia_ui_input3;
    use fuchsia_async as fasync;
    use fuchsia_zircon as zx;
    use pretty_assertions::assert_eq;
    use std::convert::TryFrom as _;

    fn input_event_from(
        keyboard_event: keyboard_binding::KeyboardEvent,
    ) -> input_device::InputEvent {
        testing_utilities::create_input_event(
            keyboard_event,
            &input_device::InputDeviceDescriptor::Fake,
            zx::Time::from_nanos(42),
            input_device::Handled::No,
        )
    }

    fn key_event_with_settings(
        keymap: Option<String>,
        settings: autorepeater::Settings,
    ) -> input_device::InputEvent {
        let keyboard_event = keyboard_binding::KeyboardEvent::new(
            fidl_fuchsia_input::Key::A,
            fidl_fuchsia_ui_input3::KeyEventType::Pressed,
        )
        .into_with_keymap(keymap)
        .into_with_autorepeat_settings(Some(settings));
        input_event_from(keyboard_event)
    }

    fn key_event(keymap: Option<String>) -> input_device::InputEvent {
        let keyboard_event = keyboard_binding::KeyboardEvent::new(
            fidl_fuchsia_input::Key::A,
            fidl_fuchsia_ui_input3::KeyEventType::Pressed,
        )
        .into_with_keymap(keymap);
        input_event_from(keyboard_event)
    }

    fn unhandled_key_event() -> input_device::UnhandledInputEvent {
        input_device::UnhandledInputEvent::try_from(key_event(None)).unwrap()
    }

    #[fasync::run_singlethreaded(test)]
    async fn keymap_id_setting() {
        #[derive(Debug)]
        struct Test {
            keymap_id: Option<finput::KeymapId>,
            expected: Option<String>,
        }
        let tests = vec![
            Test { keymap_id: None, expected: Some("US_QWERTY".to_owned()) },
            Test {
                keymap_id: Some(finput::KeymapId::UsQwerty),
                expected: Some("US_QWERTY".to_owned()),
            },
            Test {
                keymap_id: Some(finput::KeymapId::FrAzerty),
                expected: Some("FR_AZERTY".to_owned()),
            },
            Test {
                keymap_id: Some(finput::KeymapId::UsDvorak),
                expected: Some("US_DVORAK".to_owned()),
            },
        ];
        for test in tests {
            let handler = TextSettingsHandler::new(test.keymap_id.clone(), None);
            let expected = key_event(test.expected.clone());
            let result = handler.handle_unhandled_input_event(unhandled_key_event()).await;
            assert_eq!(vec![expected], result, "for: {:?}", &test);
        }
    }

    fn serve_into(
        mut server_end: fsettings::KeyboardRequestStream,
        keymap: Option<finput::KeymapId>,
        autorepeat: Option<fsettings::Autorepeat>,
    ) {
        fasync::Task::local(async move {
            if let Ok(Some(fsettings::KeyboardRequest::Watch { responder, .. })) =
                server_end.try_next().await
            {
                let settings = fsettings::KeyboardSettings {
                    keymap,
                    autorepeat,
                    ..fsettings::KeyboardSettings::EMPTY
                };
                responder.send(settings).expect("response sent");
            }
        })
        .detach();
    }

    #[fasync::run_singlethreaded(test)]
    async fn config_call_processing() {
        let handler = TextSettingsHandler::new(None, None);

        let (proxy, stream) =
            fidl::endpoints::create_proxy_and_stream::<fsettings::KeyboardMarker>().unwrap();

        // Serve a specific keyboard setting.
        serve_into(
            stream,
            Some(finput::KeymapId::FrAzerty),
            Some(fsettings::Autorepeat { delay: 43, period: 44 }),
        );

        // Start an asynchronous handler that processes keymap configuration calls
        // incoming from `server_end`.
        handler.clone().serve(proxy);

        // Setting the keymap with a hanging get that does not synchronize with the "main"
        // task of the handler inherently races with `handle_input_event`.  So, the only
        // way to test it correctly is to verify that we get a changed setting *eventually*
        // after asking the server to hand out the modified settings.  So, we loop with an
        // expectation that at some point the settings get applied.  To avoid a long timeout
        // we quit the loop if nothing happened after a generous amount of time.
        let deadline = fuchsia_async::Time::after(zx::Duration::from_seconds(5));
        let autorepeat: autorepeater::Settings = Default::default();
        loop {
            let result = handler.clone().handle_unhandled_input_event(unhandled_key_event()).await;
            let expected = key_event_with_settings(
                Some("FR_AZERTY".to_owned()),
                autorepeat
                    .clone()
                    .into_with_delay(zx::Duration::from_nanos(43))
                    .into_with_period(zx::Duration::from_nanos(44)),
            );
            if vec![expected] == result {
                break;
            }
            fuchsia_async::Timer::new(fuchsia_async::Time::after(zx::Duration::from_millis(10)))
                .await;
            let now = fuchsia_async::Time::now();
            assert!(now < deadline, "the settings did not get applied, was: {:?}", &result);
        }
    }
}
