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

//! This module contains an implementation of `LegacyIme` itself.

use {
    anyhow::{format_err, Context, Error, Result},
    fidl_fuchsia_ui_input::{self as uii, InputMethodEditorRequest as ImeReq},
    fidl_fuchsia_ui_input3 as ui_input3,
    futures::{lock::Mutex, prelude::*},
    std::{
        collections::{HashMap, HashSet},
        sync::{Arc, Weak},
    },
};

use super::{
    state::ImeState, HID_USAGE_KEY_BACKSPACE, HID_USAGE_KEY_DELETE, HID_USAGE_KEY_ENTER,
    HID_USAGE_KEY_LEFT, HID_USAGE_KEY_RIGHT,
};
use crate::{index_convert as idx, keyboard::events, text_manager::TextManager};

/// An input method provides edits and cursor updates to a text field. This Legacy Input Method
/// provides edits to a text field over the legacy pair of interfaces `InputMethodEditor` and
/// `InputMethodEditorClient`. It can provide these edits one of two ways:
///
/// 1. If `inject_input()` is called with a `KeyboardEvent`, `LegacyIme` contains an implementation
/// of a QWERTY latin keyboard input method, and will send the appropriate edits to the text field.
/// This can also handle arrow keys with modifiers to perform selection/caret movement.
/// 2. If `bind_text_field()` is called with a `TextFieldRequestStream`, `LegacyIme` can serve the
/// new `TextField` interface, translating edits or content requests from that into requests for the
/// `InputMethodEditorClient`.
#[derive(Clone)]
pub struct LegacyIme(Arc<Mutex<ImeState>>);

impl LegacyIme {
    pub fn new<I: 'static + uii::InputMethodEditorClientProxyInterface>(
        keyboard_type: uii::KeyboardType,
        action: uii::InputMethodAction,
        initial_state: uii::TextInputState,
        client: I,
        text_manager: TextManager,
    ) -> LegacyIme {
        let state = ImeState {
            text_state: initial_state,
            client: Box::new(client),
            keyboard_type,
            action,
            text_manager,
            revision: 0,
            next_text_point_id: 0,
            text_points: HashMap::new(),
            keys_pressed: HashSet::new(),
        };
        LegacyIme(Arc::new(Mutex::new(state)))
    }

    pub fn downgrade(&self) -> Weak<Mutex<ImeState>> {
        Arc::downgrade(&self.0)
    }

    pub fn upgrade(weak: &Weak<Mutex<ImeState>>) -> Option<LegacyIme> {
        weak.upgrade().map(|arc| LegacyIme(arc))
    }

    /// Binds a `TextField` to this `LegacyIme`, replacing and unbinding any previous `TextField`.
    /// All requests from the request stream will be translated into requests for
    /// `InputMethodEditorClient`, and for events, vice-versa.
    /// Handles all state updates passed down the `InputMethodEditorRequestStream`.
    pub fn bind_ime(&self, mut stream: uii::InputMethodEditorRequestStream) {
        let self_clone = self.clone();
        let self_clone_2 = self.clone();
        fuchsia_async::Task::spawn(
            async move {
                while let Some(msg) = stream
                    .try_next()
                    .await
                    .context("error reading value from IME request stream")?
                {
                    self_clone
                        .handle_ime_message(msg)
                        .await
                        .unwrap_or_else(|e| tracing::warn!("error handling ime message: {:?}", e));
                }
                Ok(())
            }
            .unwrap_or_else(|e: anyhow::Error| tracing::error!("{:?}", e))
            .then(|()| {
                async move {
                    // this runs when IME stream closes
                    // clone to ensure we only hold one lock at a time
                    let text_manager = self_clone_2.0.lock().await.text_manager.clone();
                    text_manager.update_keyboard_visibility_from_ime(&self_clone_2.0, false).await;
                }
            }),
        )
        .detach();
    }

    /// Handles a request from the legancy IME API, an InputMethodEditorRequest.
    async fn handle_ime_message(&self, msg: uii::InputMethodEditorRequest) -> Result<()> {
        match msg {
            ImeReq::SetKeyboardType { keyboard_type, .. } => {
                let mut state = self.0.lock().await;
                state.keyboard_type = keyboard_type;
                Ok(())
            }
            ImeReq::SetState { state, .. } => {
                self.set_state(state).await;
                Ok(())
            }
            ImeReq::InjectInput { .. } => {
                Err(format_err!("InjectInput is deprecated, use DispatchKey3!"))
            }
            ImeReq::DispatchKey3 { event, responder, .. } => {
                let key_event = {
                    let state = self.0.lock().await;
                    events::KeyEvent::new(&event, state.keys_pressed.clone())
                        .context("error converting key")?
                };
                self.inject_input(key_event).await?;
                self.update_keys_pressed(&event).await?;
                // False since legacy API doesn't support input handling.
                // Handling here depends on the hardcoded order of input processing.
                // This should be reworked in future IME design.
                responder.send(false).context("error sending response for DispatchKey3")
            }
            ImeReq::Show { .. } => {
                // clone to ensure we only hold one lock at a time
                let text_manager = self.0.lock().await.text_manager.clone();
                text_manager.show_keyboard().await;
                Ok(())
            }
            ImeReq::Hide { .. } => {
                // clone to ensure we only hold one lock at a time
                let text_manager = self.0.lock().await.text_manager.clone();
                text_manager.hide_keyboard().await;
                Ok(())
            }
        }
    }

    /// Sets the internal state. Expects input_state to use codeunits; automatically
    /// converts to byte indices before storing.
    pub async fn set_state(&self, input_state: uii::TextInputState) {
        let mut state = self.0.lock().await;
        state.text_state = idx::text_state_codeunit_to_byte(input_state);
        // the old C++ IME implementation didn't call did_update_state here, so this second argument is false.
        state.increment_revision(false);
    }

    /// Forwards an event to the `InputMethodEditorClient`, by sending a state update that makes no
    /// changes alongside a `KeyboardEvent`. Note that this state update will always have no changes
    /// — if you'd like to send a change, use `inject_input()`.
    pub(crate) async fn forward_event(&self, event: &events::KeyEvent) -> Result<(), Error> {
        let mut state = self.0.lock().await;
        state.forward_event(event.clone())
    }

    /// Uses `ImeState`'s internal latin input method implementation to determine the edit
    /// corresponding to `keyboard_event`, and sends this as a state update to
    /// `InputMethodEditorClient`. This method can handle arrow keys to move selections, even with
    /// modifier keys implemented correctly. However, it does *not* send the actual key event to the
    /// client; for that, you should simultaneously call `forward_event()`.
    pub(crate) async fn inject_input(&self, key_event: events::KeyEvent) -> Result<(), Error> {
        let keyboard_event: uii::KeyboardEvent =
            key_event.try_into().context("error converting key event to keyboard event")?;

        let mut state = self.0.lock().await;

        if keyboard_event.phase == uii::KeyboardEventPhase::Pressed
            || keyboard_event.phase == uii::KeyboardEventPhase::Repeat
        {
            if keyboard_event.code_point != 0 {
                state.type_keycode(keyboard_event.code_point);
                state.increment_revision(true);
            } else {
                match keyboard_event.hid_usage {
                    HID_USAGE_KEY_BACKSPACE => {
                        state.delete_backward();
                        state.increment_revision(true);
                    }
                    HID_USAGE_KEY_DELETE => {
                        state.delete_forward();
                        state.increment_revision(true);
                    }
                    HID_USAGE_KEY_LEFT => {
                        state.cursor_horizontal_move(keyboard_event.modifiers, false);
                        state.increment_revision(true);
                    }
                    HID_USAGE_KEY_RIGHT => {
                        state.cursor_horizontal_move(keyboard_event.modifiers, true);
                        state.increment_revision(true);
                    }
                    HID_USAGE_KEY_ENTER => match state.action {
                        // Pressing "Enter" inserts a newline when the input
                        // method is used to edit multi-line text. For other
                        // input actions, we report back to the
                        // client that it needs to perform some action (move
                        // focus, perform a search etc.).
                        uii::InputMethodAction::Newline => {
                            state.type_keycode('\n' as u32);
                            state.increment_revision(true);
                        }
                        _ => {
                            state
                                .client
                                .on_action(state.action)
                                .context("error sending action to ImeClient")?;
                        }
                    },
                    _ => {
                        // Not an editing key, forward the event to clients.
                        state.increment_revision(true);
                    }
                }
            }
        }
        Ok(())
    }

    /// Updates currently pressed keys.
    async fn update_keys_pressed(&self, event: &ui_input3::KeyEvent) -> Result<(), Error> {
        let type_ = event.type_.ok_or(format_err!("Expected type to be populated."))?;
        let key = event.key.ok_or(format_err!("Expected key to be populated."))?;
        let keys_pressed = &mut self.0.lock().await.keys_pressed;
        match type_ {
            ui_input3::KeyEventType::Sync | ui_input3::KeyEventType::Pressed => {
                keys_pressed.insert(key);
            }
            ui_input3::KeyEventType::Cancel | ui_input3::KeyEventType::Released => {
                keys_pressed.remove(&key);
            }
        };
        Ok(())
    }
}
