// Copyright 2013 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/base/ime/remote_input_method_win.h"

#include "base/command_line.h"
#include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/metro.h"
#include "base/win/scoped_handle.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ime/remote_input_method_delegate_win.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/rect.h"

namespace ui {
namespace {

const LANGID kFallbackLangID =
    MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT);

InputMethod* g_public_interface_ = NULL;
RemoteInputMethodPrivateWin* g_private_interface_ = NULL;

void RegisterInstance(InputMethod* public_interface,
                      RemoteInputMethodPrivateWin* private_interface) {
  CHECK(g_public_interface_ == NULL)
      << "Only one instance is supported at the same time";
  CHECK(g_private_interface_ == NULL)
      << "Only one instance is supported at the same time";
  g_public_interface_ = public_interface;
  g_private_interface_ = private_interface;
}

RemoteInputMethodPrivateWin* GetPrivate(InputMethod* public_interface) {
  if (g_public_interface_ != public_interface)
    return NULL;
  return g_private_interface_;
}

void UnregisterInstance(InputMethod* public_interface) {
  RemoteInputMethodPrivateWin* private_interface = GetPrivate(public_interface);
  if (g_public_interface_ == public_interface &&
      g_private_interface_ == private_interface) {
    g_public_interface_ = NULL;
    g_private_interface_ = NULL;
  }
}

std::string GetLocaleString(LCID Locale_id, LCTYPE locale_type) {
  wchar_t buffer[16] = {};

  //|chars_written| includes NUL terminator.
  const int chars_written =
      GetLocaleInfo(Locale_id, locale_type, buffer, arraysize(buffer));
  if (chars_written <= 1 || arraysize(buffer) < chars_written)
    return std::string();
  std::string result;
  base::WideToUTF8(buffer, chars_written - 1, &result);
  return result;
}

std::vector<int32> GetInputScopesAsInt(TextInputType text_input_type,
                                       TextInputMode text_input_mode) {
  std::vector<int32> result;
  // An empty vector represents |text_input_type| is TEXT_INPUT_TYPE_NONE.
  if (text_input_type == TEXT_INPUT_TYPE_NONE)
    return result;

  const std::vector<InputScope>& input_scopes =
      tsf_inputscope::GetInputScopes(text_input_type, text_input_mode);
  result.reserve(input_scopes.size());
  for (size_t i = 0; i < input_scopes.size(); ++i)
    result.push_back(static_cast<int32>(input_scopes[i]));
  return result;
}

std::vector<gfx::Rect> GetCompositionCharacterBounds(
    const TextInputClient* client) {
  if (!client)
    return std::vector<gfx::Rect>();

  std::vector<gfx::Rect> bounds;
  if (client->HasCompositionText()) {
    gfx::Range range;
    if (client->GetCompositionTextRange(&range)) {
      for (uint32 i = 0; i < range.length(); ++i) {
        gfx::Rect rect;
        if (!client->GetCompositionCharacterBounds(i, &rect))
          break;
        bounds.push_back(rect);
      }
    }
  }

  // Use the caret bounds as a fallback if no composition character bounds is
  // available. One typical use case is PPAPI Flash, which does not support
  // GetCompositionCharacterBounds at all. crbug.com/133472
  if (bounds.empty())
    bounds.push_back(client->GetCaretBounds());
  return bounds;
}

class RemoteInputMethodWin : public InputMethod,
                             public RemoteInputMethodPrivateWin {
 public:
  explicit RemoteInputMethodWin(internal::InputMethodDelegate* delegate)
      : delegate_(delegate),
        remote_delegate_(NULL),
        text_input_client_(NULL),
        is_candidate_popup_open_(false),
        is_ime_(false),
        langid_(kFallbackLangID) {
    RegisterInstance(this, this);
  }

  virtual ~RemoteInputMethodWin() {
    FOR_EACH_OBSERVER(InputMethodObserver,
                      observer_list_,
                      OnInputMethodDestroyed(this));
    UnregisterInstance(this);
  }

 private:
  // Overridden from InputMethod:
  virtual void SetDelegate(internal::InputMethodDelegate* delegate) override {
    delegate_ = delegate;
  }

  virtual void Init(bool focused) override {
  }

  virtual void OnFocus() override {
  }

  virtual void OnBlur() override {
  }

  virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
                                        NativeEventResult* result) override {
    return false;
  }

  virtual void SetFocusedTextInputClient(TextInputClient* client) override {
    std::vector<int32> prev_input_scopes;
    std::swap(input_scopes_, prev_input_scopes);
    std::vector<gfx::Rect> prev_bounds;
    std::swap(composition_character_bounds_, prev_bounds);
    if (client) {
      input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
                                          client->GetTextInputMode());
      composition_character_bounds_ = GetCompositionCharacterBounds(client);
    }

    const bool text_input_client_changed = text_input_client_ != client;
    text_input_client_ = client;
    if (text_input_client_changed) {
      FOR_EACH_OBSERVER(InputMethodObserver,
                        observer_list_,
                        OnTextInputStateChanged(client));
    }

    if (!remote_delegate_ || (prev_input_scopes == input_scopes_ &&
                              prev_bounds == composition_character_bounds_))
      return;
    remote_delegate_->OnTextInputClientUpdated(input_scopes_,
                                               composition_character_bounds_);
  }

  virtual void DetachTextInputClient(TextInputClient* client) override {
    if (text_input_client_ != client)
      return;
    SetFocusedTextInputClient(NULL);
  }

  virtual TextInputClient* GetTextInputClient() const override {
    return text_input_client_;
  }

  virtual bool DispatchKeyEvent(const ui::KeyEvent& event) override {
    if (event.HasNativeEvent()) {
      const base::NativeEvent& native_key_event = event.native_event();
      if (native_key_event.message != WM_CHAR)
        return false;
      if (!text_input_client_)
        return false;
      text_input_client_->InsertChar(
          static_cast<base::char16>(native_key_event.wParam),
          ui::GetModifiersFromKeyState());
      return true;
    }

    if (event.is_char()) {
      if (text_input_client_) {
        text_input_client_->InsertChar(
            static_cast<base::char16>(event.key_code()),
            ui::GetModifiersFromKeyState());
      }
      return true;
    }
    if (!delegate_)
      return false;
    return delegate_->DispatchKeyEventPostIME(event);
  }

  virtual void OnTextInputTypeChanged(const TextInputClient* client) override {
    if (!text_input_client_ || text_input_client_ != client)
      return;
    std::vector<int32> prev_input_scopes;
    std::swap(input_scopes_, prev_input_scopes);
    input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
                                        client->GetTextInputMode());
    if (input_scopes_ != prev_input_scopes && remote_delegate_) {
      remote_delegate_->OnTextInputClientUpdated(
          input_scopes_, composition_character_bounds_);
    }
  }

  virtual void OnCaretBoundsChanged(const TextInputClient* client) override {
    if (!text_input_client_ || text_input_client_ != client)
      return;
    std::vector<gfx::Rect> prev_rects;
    std::swap(composition_character_bounds_, prev_rects);
    composition_character_bounds_ = GetCompositionCharacterBounds(client);
    if (composition_character_bounds_ != prev_rects && remote_delegate_) {
      remote_delegate_->OnTextInputClientUpdated(
          input_scopes_, composition_character_bounds_);
    }
  }

  virtual void CancelComposition(const TextInputClient* client) override {
    if (CanSendRemoteNotification(client))
      remote_delegate_->CancelComposition();
  }

  virtual void OnInputLocaleChanged() override {
  }

  virtual std::string GetInputLocale() override {
    const LCID locale_id = MAKELCID(langid_, SORT_DEFAULT);
    std::string language =
        GetLocaleString(locale_id, LOCALE_SISO639LANGNAME);
    if (SUBLANGID(langid_) == SUBLANG_NEUTRAL || language.empty())
      return language;
    const std::string& region =
        GetLocaleString(locale_id, LOCALE_SISO3166CTRYNAME);
    if (region.empty())
      return language;
    return language.append(1, '-').append(region);
  }

  virtual bool IsActive() override {
    return true;  // always turned on
  }

  virtual TextInputType GetTextInputType() const override {
    return text_input_client_ ? text_input_client_->GetTextInputType()
                              : TEXT_INPUT_TYPE_NONE;
  }

  virtual TextInputMode GetTextInputMode() const override {
    return text_input_client_ ? text_input_client_->GetTextInputMode()
                              : TEXT_INPUT_MODE_DEFAULT;
  }

  virtual bool CanComposeInline() const override {
    return text_input_client_ ? text_input_client_->CanComposeInline() : true;
  }

  virtual bool IsCandidatePopupOpen() const override {
    return is_candidate_popup_open_;
  }

  virtual void ShowImeIfNeeded() override {
  }

  virtual void AddObserver(InputMethodObserver* observer) override {
    observer_list_.AddObserver(observer);
  }

  virtual void RemoveObserver(InputMethodObserver* observer) override {
    observer_list_.RemoveObserver(observer);
  }

  // Overridden from RemoteInputMethodPrivateWin:
  virtual void SetRemoteDelegate(
      internal::RemoteInputMethodDelegateWin* delegate) override{
    remote_delegate_ = delegate;

    // Sync initial state.
    if (remote_delegate_) {
      remote_delegate_->OnTextInputClientUpdated(
          input_scopes_, composition_character_bounds_);
    }
  }

  virtual void OnCandidatePopupChanged(bool visible) override {
    is_candidate_popup_open_ = visible;
    if (!text_input_client_)
      return;
    // TODO(kochi): Support 'update' case, in addition to show/hide.
    // http://crbug.com/238585
    if (visible)
      text_input_client_->OnCandidateWindowShown();
    else
      text_input_client_->OnCandidateWindowHidden();
  }

  virtual void OnInputSourceChanged(LANGID langid, bool /*is_ime*/) override {
    // Note: Currently |is_ime| is not utilized yet.
    const bool changed = (langid_ != langid);
    langid_ = langid;
    if (changed && GetTextInputClient())
      GetTextInputClient()->OnInputMethodChanged();
  }

  virtual void OnCompositionChanged(
      const CompositionText& composition_text) override {
    if (!text_input_client_)
      return;
    text_input_client_->SetCompositionText(composition_text);
  }

  virtual void OnTextCommitted(const base::string16& text) override {
    if (!text_input_client_)
      return;
    if (text_input_client_->GetTextInputType() == TEXT_INPUT_TYPE_NONE) {
      // According to the comment in text_input_client.h,
      // TextInputClient::InsertText should never be called when the
      // text input type is TEXT_INPUT_TYPE_NONE.
      for (size_t i = 0; i < text.size(); ++i)
        text_input_client_->InsertChar(text[i], 0);
      return;
    }
    text_input_client_->InsertText(text);
  }

  bool CanSendRemoteNotification(
      const TextInputClient* text_input_client) const {
    return text_input_client_ &&
           text_input_client_ == text_input_client &&
           remote_delegate_;
  }

  ObserverList<InputMethodObserver> observer_list_;

  internal::InputMethodDelegate* delegate_;
  internal::RemoteInputMethodDelegateWin* remote_delegate_;

  TextInputClient* text_input_client_;
  std::vector<int32> input_scopes_;
  std::vector<gfx::Rect> composition_character_bounds_;
  bool is_candidate_popup_open_;
  bool is_ime_;
  LANGID langid_;

  DISALLOW_COPY_AND_ASSIGN(RemoteInputMethodWin);
};

}  // namespace

bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) {
  // If the remote input method is already registered then don't do it again.
  if (ui::g_public_interface_ && ui::g_private_interface_)
    return false;

  DWORD process_id = 0;
  if (GetWindowThreadProcessId(widget, &process_id) == 0)
    return false;
  base::win::ScopedHandle process_handle(::OpenProcess(
      PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id));
  if (!process_handle.IsValid())
    return false;
  return base::win::IsProcessImmersive(process_handle.Get()) ||
         CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kViewerConnect);
}

RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {}

scoped_ptr<InputMethod> CreateRemoteInputMethodWin(
    internal::InputMethodDelegate* delegate) {
  return scoped_ptr<InputMethod>(new RemoteInputMethodWin(delegate));
}

// static
RemoteInputMethodPrivateWin* RemoteInputMethodPrivateWin::Get(
    InputMethod* input_method) {
  return GetPrivate(input_method);
}

}  // namespace ui
