// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/mus/input_method_mus.h"

#include <utility>

#include "base/memory/ptr_util.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "services/ui/public/interfaces/ime/ime.mojom.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/mus/text_input_client_impl.h"
#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/window.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/event.h"
#include "ui/platform_window/mojo/ime_type_converters.h"
#include "ui/platform_window/mojo/text_input_state.mojom.h"

using ui::mojom::EventResult;

namespace aura {

////////////////////////////////////////////////////////////////////////////////
// InputMethodMus, public:

InputMethodMus::InputMethodMus(ui::internal::InputMethodDelegate* delegate,
                               Window* window)
    : window_(window) {
  SetDelegate(delegate);
}

InputMethodMus::~InputMethodMus() {
  // Mus won't dispatch the next key event until the existing one is acked. We
  // may have KeyEvents sent to IME and awaiting the result, we need to ack
  // them otherwise mus won't process the next event until it times out.
  AckPendingCallbacksUnhandled();
}

void InputMethodMus::Init(service_manager::Connector* connector) {
  if (connector)
    connector->BindInterface(ui::mojom::kServiceName, &ime_driver_);
}

ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent(
    ui::KeyEvent* event,
    std::unique_ptr<EventResultCallback> ack_callback) {
  DCHECK(event->type() == ui::ET_KEY_PRESSED ||
         event->type() == ui::ET_KEY_RELEASED);

  // If no text input client, do nothing.
  if (!GetTextInputClient()) {
    ui::EventDispatchDetails dispatch_details = DispatchKeyEventPostIME(event);
    if (ack_callback) {
      ack_callback->Run(event->handled() ? EventResult::HANDLED
                                         : EventResult::UNHANDLED);
    }
    return dispatch_details;
  }

  return SendKeyEventToInputMethod(*event, std::move(ack_callback));
}

////////////////////////////////////////////////////////////////////////////////
// InputMethodMus, ui::InputMethod implementation:

void InputMethodMus::OnFocus() {
  InputMethodBase::OnFocus();
  UpdateTextInputType();
}

void InputMethodMus::OnBlur() {
  InputMethodBase::OnBlur();
  UpdateTextInputType();
}

bool InputMethodMus::OnUntranslatedIMEMessage(const base::NativeEvent& event,
                                              NativeEventResult* result) {
  // This method is not called on non-Windows platforms. See the comments for
  // ui::InputMethod::OnUntranslatedIMEMessage().
  return false;
}

ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent(ui::KeyEvent* event) {
  ui::EventDispatchDetails dispatch_details = DispatchKeyEvent(event, nullptr);
  // Mark the event as handled so that EventGenerator doesn't attempt to
  // deliver event as well.
  event->SetHandled();
  return dispatch_details;
}

void InputMethodMus::OnTextInputTypeChanged(const ui::TextInputClient* client) {
  InputMethodBase::OnTextInputTypeChanged(client);
  if (!IsTextInputClientFocused(client))
    return;

  UpdateTextInputType();

  if (input_method_)
    input_method_->OnTextInputTypeChanged(client->GetTextInputType());
}

void InputMethodMus::OnCaretBoundsChanged(const ui::TextInputClient* client) {
  if (!IsTextInputClientFocused(client))
    return;

  if (input_method_)
    input_method_->OnCaretBoundsChanged(client->GetCaretBounds());
}

void InputMethodMus::CancelComposition(const ui::TextInputClient* client) {
  if (!IsTextInputClientFocused(client))
    return;

  if (input_method_)
    input_method_->CancelComposition();
}

void InputMethodMus::OnInputLocaleChanged() {
  // TODO(moshayedi): crbug.com/637418. Not supported in ChromeOS. Investigate
  // whether we want to support this or not.
}

bool InputMethodMus::IsCandidatePopupOpen() const {
  // TODO(moshayedi): crbug.com/637416. Implement this properly when we have a
  // mean for displaying candidate list popup.
  return false;
}

ui::EventDispatchDetails InputMethodMus::SendKeyEventToInputMethod(
    const ui::KeyEvent& event,
    std::unique_ptr<EventResultCallback> ack_callback) {
  if (!input_method_) {
    // This code path is hit in tests that don't connect to the server.
    DCHECK(!ack_callback);
    std::unique_ptr<ui::Event> event_clone = ui::Event::Clone(event);
    return DispatchKeyEventPostIME(event_clone->AsKeyEvent());
  }
  // IME driver will notify us whether it handled the event or not by calling
  // ProcessKeyEventCallback(), in which we will run the |ack_callback| to tell
  // the window server if client handled the event or not.
  pending_callbacks_.push_back(std::move(ack_callback));
  input_method_->ProcessKeyEvent(
      ui::Event::Clone(event),
      base::Bind(&InputMethodMus::ProcessKeyEventCallback,
                 base::Unretained(this), event));

  return ui::EventDispatchDetails();
}

void InputMethodMus::OnDidChangeFocusedClient(
    ui::TextInputClient* focused_before,
    ui::TextInputClient* focused) {
  InputMethodBase::OnDidChangeFocusedClient(focused_before, focused);
  UpdateTextInputType();

  // TODO(moshayedi): crbug.com/681563. Handle when there is no focused clients.
  if (!focused)
    return;

  text_input_client_ =
      std::make_unique<TextInputClientImpl>(focused, delegate());

  // We are about to close the pipe with pending callbacks. Closing the pipe
  // results in none of the callbacks being run. We have to run the callbacks
  // else mus won't process the next event immediately.
  AckPendingCallbacksUnhandled();

  if (ime_driver_) {
    ui::mojom::StartSessionDetailsPtr details =
        ui::mojom::StartSessionDetails::New();
    details->client =
        text_input_client_->CreateInterfacePtrAndBind().PassInterface();
    details->input_method_request = MakeRequest(&input_method_ptr_);
    input_method_ = input_method_ptr_.get();
    details->text_input_type = focused->GetTextInputType();
    details->text_input_mode = focused->GetTextInputMode();
    details->text_direction = focused->GetTextDirection();
    details->text_input_flags = focused->GetTextInputFlags();
    details->caret_bounds = focused->GetCaretBounds();
    ime_driver_->StartSession(std::move(details));
  }
}

void InputMethodMus::UpdateTextInputType() {
  ui::TextInputType type = GetTextInputType();
  ui::mojom::TextInputStatePtr state = ui::mojom::TextInputState::New();
  state->type = mojo::ConvertTo<ui::mojom::TextInputType>(type);
  if (window_) {
    WindowPortMus* window_impl_mus = WindowPortMus::Get(window_);
    if (type != ui::TEXT_INPUT_TYPE_NONE)
      window_impl_mus->SetImeVisibility(true, std::move(state));
    else
      window_impl_mus->SetTextInputState(std::move(state));
  }
}

void InputMethodMus::AckPendingCallbacksUnhandled() {
  for (auto& callback_ptr : pending_callbacks_) {
    if (callback_ptr)
      callback_ptr->Run(EventResult::UNHANDLED);
  }
  pending_callbacks_.clear();
}

void InputMethodMus::ProcessKeyEventCallback(
    const ui::KeyEvent& event,
    bool handled) {
  // Remove the callback as DispatchKeyEventPostIME() may lead to calling
  // AckPendingCallbacksUnhandled(), which mutates |pending_callbacks_|.
  DCHECK(!pending_callbacks_.empty());
  std::unique_ptr<EventResultCallback> ack_callback =
      std::move(pending_callbacks_.front());
  pending_callbacks_.pop_front();

  // |ack_callback| can be null if the standard form of DispatchKeyEvent() is
  // called instead of the version which provides a callback. In mus+ash we
  // use the version with callback, but some unittests use the standard form.
  if (ack_callback)
    ack_callback->Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED);
}

}  // namespace aura
