// Copyright (c) 2012 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 "chrome/browser/chromeos/input_method/input_method_manager_impl.h"

#include <algorithm>  // std::find

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
#include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chromeos/ime/component_extension_ime_manager.h"
#include "chromeos/ime/extension_ime_util.h"
#include "chromeos/ime/input_method_delegate.h"
#include "chromeos/ime/xkeyboard.h"
#include "third_party/icu/source/common/unicode/uloc.h"
#include "ui/base/accelerators/accelerator.h"

namespace chromeos {
namespace input_method {

namespace {

const char nacl_mozc_jp_id[] =
    "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp";

bool Contains(const std::vector<std::string>& container,
              const std::string& value) {
  return std::find(container.begin(), container.end(), value) !=
      container.end();
}

}  // namespace

bool InputMethodManagerImpl::IsLoginKeyboard(
    const std::string& layout) const {
  const InputMethodDescriptor* ime =
      util_.GetInputMethodDescriptorFromId(layout);
  return ime ? ime->is_login_keyboard() : false;
}

InputMethodManagerImpl::InputMethodManagerImpl(
    scoped_ptr<InputMethodDelegate> delegate)
    : delegate_(delegate.Pass()),
      state_(STATE_LOGIN_SCREEN),
      util_(delegate_.get(), GetSupportedInputMethods()),
      component_extension_ime_manager_(new ComponentExtensionIMEManager()),
      weak_ptr_factory_(this) {
}

InputMethodManagerImpl::~InputMethodManagerImpl() {
  if (candidate_window_controller_.get())
    candidate_window_controller_->RemoveObserver(this);
}

void InputMethodManagerImpl::AddObserver(
    InputMethodManager::Observer* observer) {
  observers_.AddObserver(observer);
}

void InputMethodManagerImpl::AddCandidateWindowObserver(
    InputMethodManager::CandidateWindowObserver* observer) {
  candidate_window_observers_.AddObserver(observer);
}

void InputMethodManagerImpl::RemoveObserver(
    InputMethodManager::Observer* observer) {
  observers_.RemoveObserver(observer);
}

void InputMethodManagerImpl::RemoveCandidateWindowObserver(
    InputMethodManager::CandidateWindowObserver* observer) {
  candidate_window_observers_.RemoveObserver(observer);
}

void InputMethodManagerImpl::SetState(State new_state) {
  const State old_state = state_;
  state_ = new_state;
  switch (state_) {
    case STATE_LOGIN_SCREEN:
      break;
    case STATE_BROWSER_SCREEN:
      if (old_state == STATE_LOCK_SCREEN)
        OnScreenUnlocked();
      break;
    case STATE_LOCK_SCREEN:
      OnScreenLocked();
      break;
    case STATE_TERMINATING: {
      if (candidate_window_controller_.get())
        candidate_window_controller_.reset();
      break;
    }
  }
}

scoped_ptr<InputMethodDescriptors>
InputMethodManagerImpl::GetSupportedInputMethods() const {
  return whitelist_.GetSupportedInputMethods();
}

scoped_ptr<InputMethodDescriptors>
InputMethodManagerImpl::GetActiveInputMethods() const {
  scoped_ptr<InputMethodDescriptors> result(new InputMethodDescriptors);
  // Build the active input method descriptors from the active input
  // methods cache |active_input_method_ids_|.
  for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
    const std::string& input_method_id = active_input_method_ids_[i];
    const InputMethodDescriptor* descriptor =
        util_.GetInputMethodDescriptorFromId(input_method_id);
    if (descriptor) {
      result->push_back(*descriptor);
    } else {
      std::map<std::string, InputMethodDescriptor>::const_iterator ix =
          extra_input_methods_.find(input_method_id);
      if (ix != extra_input_methods_.end())
        result->push_back(ix->second);
      else
        DVLOG(1) << "Descriptor is not found for: " << input_method_id;
    }
  }
  if (result->empty()) {
    // Initially |active_input_method_ids_| is empty. browser_tests might take
    // this path.
    result->push_back(
        InputMethodUtil::GetFallbackInputMethodDescriptor());
  }
  return result.Pass();
}

const std::vector<std::string>&
InputMethodManagerImpl::GetActiveInputMethodIds() const {
  return active_input_method_ids_;
}

size_t InputMethodManagerImpl::GetNumActiveInputMethods() const {
  return active_input_method_ids_.size();
}

void InputMethodManagerImpl::EnableLayouts(const std::string& language_code,
                                           const std::string& initial_layout) {
  if (state_ == STATE_TERMINATING)
    return;

  std::vector<std::string> candidates;
  // Add input methods associated with the language.
  util_.GetInputMethodIdsFromLanguageCode(language_code,
                                          kKeyboardLayoutsOnly,
                                          &candidates);
  // Add the hardware keyboard as well. We should always add this so users
  // can use the hardware keyboard on the login screen and the screen locker.
  candidates.push_back(util_.GetHardwareInputMethodId());

  std::vector<std::string> layouts;
  // First, add the initial input method ID, if it's requested, to
  // layouts, so it appears first on the list of active input
  // methods at the input language status menu.
  if (util_.IsValidInputMethodId(initial_layout) &&
      IsLoginKeyboard(initial_layout)) {
    layouts.push_back(initial_layout);
  } else if (!initial_layout.empty()) {
    DVLOG(1) << "EnableLayouts: ignoring non-keyboard or invalid ID: "
             << initial_layout;
  }

  // Add candidates to layouts, while skipping duplicates.
  for (size_t i = 0; i < candidates.size(); ++i) {
    const std::string& candidate = candidates[i];
    // Not efficient, but should be fine, as the two vectors are very
    // short (2-5 items).
    if (!Contains(layouts, candidate) && IsLoginKeyboard(candidate))
      layouts.push_back(candidate);
  }

  active_input_method_ids_.swap(layouts);

  // Initialize candidate window controller and widgets such as
  // candidate window, infolist and mode indicator.  Note, mode
  // indicator is used by only keyboard layout input methods.
  if (active_input_method_ids_.size() > 1)
    MaybeInitializeCandidateWindowController();

  ChangeInputMethod(initial_layout);  // you can pass empty |initial_layout|.
}

// Adds new input method to given list.
bool InputMethodManagerImpl::EnableInputMethodImpl(
    const std::string& input_method_id,
    std::vector<std::string>* new_active_input_method_ids) const {
  DCHECK(new_active_input_method_ids);
  if (!util_.IsValidInputMethodId(input_method_id)) {
    DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
    return false;
  }

  if (!Contains(*new_active_input_method_ids, input_method_id))
    new_active_input_method_ids->push_back(input_method_id);

  return true;
}

// Starts or stops the system input method framework as needed.
void InputMethodManagerImpl::ReconfigureIMFramework() {
  if (component_extension_ime_manager_->IsInitialized())
    LoadNecessaryComponentExtensions();

  const bool need_engine =
      !ContainsOnlyKeyboardLayout(active_input_method_ids_);

  // Initialize candidate window controller and widgets such as
  // candidate window, infolist and mode indicator.  Note, mode
  // indicator is used by only keyboard layout input methods.
  if (need_engine || active_input_method_ids_.size() > 1)
    MaybeInitializeCandidateWindowController();
}

bool InputMethodManagerImpl::EnableInputMethod(
    const std::string& input_method_id) {
  if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids_))
    return false;

  ReconfigureIMFramework();
  return true;
}

bool InputMethodManagerImpl::EnableInputMethods(
    const std::vector<std::string>& new_active_input_method_ids) {
  if (state_ == STATE_TERMINATING)
    return false;

  // Filter unknown or obsolete IDs.
  std::vector<std::string> new_active_input_method_ids_filtered;

  for (size_t i = 0; i < new_active_input_method_ids.size(); ++i)
    EnableInputMethodImpl(new_active_input_method_ids[i],
                          &new_active_input_method_ids_filtered);

  if (new_active_input_method_ids_filtered.empty()) {
    DVLOG(1) << "EnableInputMethods: No valid input method ID";
    return false;
  }

  // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to
  // keep relative order of the extension input method IDs.
  for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
    const std::string& input_method_id = active_input_method_ids_[i];
    if (extension_ime_util::IsExtensionIME(input_method_id))
      new_active_input_method_ids_filtered.push_back(input_method_id);
  }
  active_input_method_ids_.swap(new_active_input_method_ids_filtered);

  ReconfigureIMFramework();

  // If |current_input_method| is no longer in |active_input_method_ids_|,
  // ChangeInputMethod() picks the first one in |active_input_method_ids_|.
  ChangeInputMethod(current_input_method_.id());
  return true;
}

void InputMethodManagerImpl::ChangeInputMethod(
    const std::string& input_method_id) {
  ChangeInputMethodInternal(input_method_id, false);
}

bool InputMethodManagerImpl::ChangeInputMethodInternal(
    const std::string& input_method_id,
    bool show_message) {
  if (state_ == STATE_TERMINATING)
    return false;

  std::string input_method_id_to_switch = input_method_id;

  // Sanity check.
  if (!InputMethodIsActivated(input_method_id)) {
    scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
    DCHECK(!input_methods->empty());
    input_method_id_to_switch = input_methods->at(0).id();
    if (!input_method_id.empty()) {
      DVLOG(1) << "Can't change the current input method to "
               << input_method_id << " since the engine is not enabled. "
               << "Switch to " << input_method_id_to_switch << " instead.";
    }
  }

  if (!component_extension_ime_manager_->IsInitialized() &&
      !InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch)) {
    // We can't change input method before the initialization of
    // component extension ime manager.  ChangeInputMethod will be
    // called with |pending_input_method_| when the initialization is
    // done.
    pending_input_method_ = input_method_id_to_switch;
    return false;
  }
  pending_input_method_.clear();

  // Hide candidate window and info list.
  if (candidate_window_controller_.get())
    candidate_window_controller_->Hide();

  // Disable the current engine handler.
  IBusEngineHandlerInterface* engine =
      IBusBridge::Get()->GetCurrentEngineHandler();
  if (engine)
    engine->Disable();

  // Configure the next engine handler.
  if (InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch)) {
    IBusBridge::Get()->SetCurrentEngineHandler(NULL);
  } else {
    IBusEngineHandlerInterface* next_engine =
        IBusBridge::Get()->SetCurrentEngineHandlerById(
            input_method_id_to_switch);

    if (next_engine)
      next_engine->Enable();
  }

  // TODO(komatsu): Check if it is necessary to perform the above routine
  // when the current input method is equal to |input_method_id_to_swich|.
  if (current_input_method_.id() != input_method_id_to_switch) {
    // Clear property list.  Property list would be updated by
    // extension IMEs via InputMethodEngine::(Set|Update)MenuItems.
    // If the current input method is a keyboard layout, empty
    // properties are sufficient.
    const InputMethodPropertyList empty_property_list;
    SetCurrentInputMethodProperties(empty_property_list);

    const InputMethodDescriptor* descriptor = NULL;
    if (extension_ime_util::IsExtensionIME(input_method_id_to_switch)) {
      DCHECK(extra_input_methods_.find(input_method_id_to_switch) !=
             extra_input_methods_.end());
      descriptor = &(extra_input_methods_[input_method_id_to_switch]);
    } else {
      descriptor =
          util_.GetInputMethodDescriptorFromId(input_method_id_to_switch);
    }
    DCHECK(descriptor);

    previous_input_method_ = current_input_method_;
    current_input_method_ = *descriptor;
  }

  // Change the keyboard layout to a preferred layout for the input method.
  if (!xkeyboard_->SetCurrentKeyboardLayoutByName(
          current_input_method_.GetPreferredKeyboardLayout())) {
    LOG(ERROR) << "Failed to change keyboard layout to "
               << current_input_method_.GetPreferredKeyboardLayout();
  }

  // Update input method indicators (e.g. "US", "DV") in Chrome windows.
  FOR_EACH_OBSERVER(InputMethodManager::Observer,
                    observers_,
                    InputMethodChanged(this, show_message));
  return true;
}

void InputMethodManagerImpl::OnComponentExtensionInitialized(
    scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
  DCHECK(thread_checker_.CalledOnValidThread());
  component_extension_ime_manager_->Initialize(delegate.Pass());
  util_.SetComponentExtensions(
      component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());

  LoadNecessaryComponentExtensions();

  if (!pending_input_method_.empty())
    ChangeInputMethodInternal(pending_input_method_, false);

}

void InputMethodManagerImpl::LoadNecessaryComponentExtensions() {
  if (!component_extension_ime_manager_->IsInitialized())
    return;
  // Load component extensions but also update |active_input_method_ids_| as
  // some component extension IMEs may have been removed from the Chrome OS
  // image. If specified component extension IME no longer exists, falling back
  // to an existing IME.
  std::vector<std::string> unfiltered_input_method_ids =
      active_input_method_ids_;
  active_input_method_ids_.clear();
  for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) {
    if (!extension_ime_util::IsComponentExtensionIME(
        unfiltered_input_method_ids[i])) {
      // Legacy IMEs or xkb layouts are alwayes active.
      active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
    } else if (component_extension_ime_manager_->IsWhitelisted(
        unfiltered_input_method_ids[i])) {
      component_extension_ime_manager_->LoadComponentExtensionIME(
          unfiltered_input_method_ids[i]);
      active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
    }
  }
}

void InputMethodManagerImpl::ActivateInputMethodProperty(
    const std::string& key) {
  DCHECK(!key.empty());

  for (size_t i = 0; i < property_list_.size(); ++i) {
    if (property_list_[i].key == key) {
      IBusEngineHandlerInterface* engine =
          IBusBridge::Get()->GetCurrentEngineHandler();
      if (engine)
        engine->PropertyActivate(key);
      return;
    }
  }

  DVLOG(1) << "ActivateInputMethodProperty: unknown key: " << key;
}

void InputMethodManagerImpl::AddInputMethodExtension(
    const std::string& id,
    const std::string& name,
    const std::vector<std::string>& layouts,
    const std::vector<std::string>& languages,
    const GURL& options_url,
    const GURL& inputview_url,
    InputMethodEngineInterface* engine) {
  if (state_ == STATE_TERMINATING)
    return;

  if (!extension_ime_util::IsExtensionIME(id) &&
      !extension_ime_util::IsComponentExtensionIME(id)) {
    DVLOG(1) << id << " is not a valid extension input method ID.";
    return;
  }

  extra_input_methods_[id] = InputMethodDescriptor(
      id, name, layouts, languages, false, options_url, inputview_url);
  if (Contains(enabled_extension_imes_, id) &&
      !extension_ime_util::IsComponentExtensionIME(id)) {
    if (!Contains(active_input_method_ids_, id)) {
      active_input_method_ids_.push_back(id);
    } else {
      DVLOG(1) << "AddInputMethodExtension: alread added: "
               << id << ", " << name;
      // Call Start() anyway, just in case.
    }

    // Ensure that the input method daemon is running.
    MaybeInitializeCandidateWindowController();
  }
}

void InputMethodManagerImpl::RemoveInputMethodExtension(const std::string& id) {
  if (!extension_ime_util::IsExtensionIME(id))
    DVLOG(1) << id << " is not a valid extension input method ID.";

  std::vector<std::string>::iterator i = std::find(
      active_input_method_ids_.begin(), active_input_method_ids_.end(), id);
  if (i != active_input_method_ids_.end())
    active_input_method_ids_.erase(i);
  extra_input_methods_.erase(id);

  // If |current_input_method| is no longer in |active_input_method_ids_|,
  // switch to the first one in |active_input_method_ids_|.
  ChangeInputMethod(current_input_method_.id());

  if (IBusBridge::Get()->GetCurrentEngineHandler() ==
      IBusBridge::Get()->GetEngineHandler(id))
    IBusBridge::Get()->SetCurrentEngineHandler(NULL);
}

void InputMethodManagerImpl::GetInputMethodExtensions(
    InputMethodDescriptors* result) {
  // Build the extension input method descriptors from the extra input
  // methods cache |extra_input_methods_|.
  std::map<std::string, InputMethodDescriptor>::iterator iter;
  for (iter = extra_input_methods_.begin(); iter != extra_input_methods_.end();
       ++iter) {
    if (extension_ime_util::IsExtensionIME(iter->first))
      result->push_back(iter->second);
  }
}

void InputMethodManagerImpl::SetEnabledExtensionImes(
    std::vector<std::string>* ids) {
  enabled_extension_imes_.clear();
  enabled_extension_imes_.insert(enabled_extension_imes_.end(),
                                 ids->begin(),
                                 ids->end());

  bool active_imes_changed = false;

  for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter =
       extra_input_methods_.begin(); extra_iter != extra_input_methods_.end();
       ++extra_iter) {
    if (extension_ime_util::IsComponentExtensionIME(
        extra_iter->first))
      continue;  // Do not filter component extension.
    std::vector<std::string>::iterator active_iter = std::find(
        active_input_method_ids_.begin(), active_input_method_ids_.end(),
        extra_iter->first);

    bool active = active_iter != active_input_method_ids_.end();
    bool enabled = Contains(enabled_extension_imes_, extra_iter->first);

    if (active && !enabled)
      active_input_method_ids_.erase(active_iter);

    if (!active && enabled)
      active_input_method_ids_.push_back(extra_iter->first);

    if (active == !enabled)
      active_imes_changed = true;
  }

  if (active_imes_changed) {
    MaybeInitializeCandidateWindowController();

    // If |current_input_method| is no longer in |active_input_method_ids_|,
    // switch to the first one in |active_input_method_ids_|.
    ChangeInputMethod(current_input_method_.id());
  }
}

void InputMethodManagerImpl::SetInputMethodDefault() {
  // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
  // and US dvorak keyboard layouts.
  if (g_browser_process && g_browser_process->local_state()) {
    const std::string locale = g_browser_process->GetApplicationLocale();
    // If the preferred keyboard for the login screen has been saved, use it.
    PrefService* prefs = g_browser_process->local_state();
    std::string initial_input_method_id =
        prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
    if (initial_input_method_id.empty()) {
      // If kPreferredKeyboardLayout is not specified, use the hardware layout.
      initial_input_method_id =
          GetInputMethodUtil()->GetHardwareInputMethodId();
    }
    EnableLayouts(locale, initial_input_method_id);
  }
}

bool InputMethodManagerImpl::SwitchToNextInputMethod() {
  // Sanity checks.
  if (active_input_method_ids_.empty()) {
    DVLOG(1) << "active input method is empty";
    return false;
  }

  if (current_input_method_.id().empty()) {
    DVLOG(1) << "current_input_method_ is unknown";
    return false;
  }

  // Do not consume key event if there is only one input method is enabled.
  // Ctrl+Space or Alt+Shift may be used by other application.
  if (active_input_method_ids_.size() == 1)
    return false;

  // Find the next input method and switch to it.
  SwitchToNextInputMethodInternal(active_input_method_ids_,
                                  current_input_method_.id());
  return true;
}

bool InputMethodManagerImpl::SwitchToPreviousInputMethod(
    const ui::Accelerator& accelerator) {
  // Sanity check.
  if (active_input_method_ids_.empty()) {
    DVLOG(1) << "active input method is empty";
    return false;
  }

  // Do not consume key event if there is only one input method is enabled.
  // Ctrl+Space or Alt+Shift may be used by other application.
  if (active_input_method_ids_.size() == 1)
    return false;

  if (accelerator.type() == ui::ET_KEY_RELEASED)
    return true;

  if (previous_input_method_.id().empty() ||
      previous_input_method_.id() == current_input_method_.id()) {
    return SwitchToNextInputMethod();
  }

  std::vector<std::string>::const_iterator iter =
      std::find(active_input_method_ids_.begin(),
                active_input_method_ids_.end(),
                previous_input_method_.id());
  if (iter == active_input_method_ids_.end()) {
    // previous_input_method_ is not supported.
    return SwitchToNextInputMethod();
  }
  ChangeInputMethodInternal(*iter, true);
  return true;
}

bool InputMethodManagerImpl::SwitchInputMethod(
    const ui::Accelerator& accelerator) {
  // Sanity check.
  if (active_input_method_ids_.empty()) {
    DVLOG(1) << "active input method is empty";
    return false;
  }

  // Get the list of input method ids for the |accelerator|. For example, get
  // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR.
  std::vector<std::string> input_method_ids_to_switch;
  switch (accelerator.key_code()) {
    case ui::VKEY_CONVERT:  // Henkan key on JP106 keyboard
      input_method_ids_to_switch.push_back(nacl_mozc_jp_id);
      break;
    case ui::VKEY_NONCONVERT:  // Muhenkan key on JP106 keyboard
      input_method_ids_to_switch.push_back("xkb:jp::jpn");
      break;
    case ui::VKEY_DBE_SBCSCHAR:  // ZenkakuHankaku key on JP106 keyboard
    case ui::VKEY_DBE_DBCSCHAR:
      input_method_ids_to_switch.push_back(nacl_mozc_jp_id);
      input_method_ids_to_switch.push_back("xkb:jp::jpn");
      break;
    default:
      NOTREACHED();
      break;
  }
  if (input_method_ids_to_switch.empty()) {
    DVLOG(1) << "Unexpected VKEY: " << accelerator.key_code();
    return false;
  }

  // Obtain the intersection of input_method_ids_to_switch and
  // active_input_method_ids_. The order of IDs in active_input_method_ids_ is
  // preserved.
  std::vector<std::string> ids;
  for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) {
    const std::string& id = input_method_ids_to_switch[i];
    if (Contains(active_input_method_ids_, id))
      ids.push_back(id);
  }
  if (ids.empty()) {
    // No input method for the accelerator is active. For example, we should
    // just ignore VKEY_HANGUL when mozc-hangul is not active.
    return false;
  }

  SwitchToNextInputMethodInternal(ids, current_input_method_.id());
  return true;  // consume the accelerator.
}

void InputMethodManagerImpl::SwitchToNextInputMethodInternal(
    const std::vector<std::string>& input_method_ids,
    const std::string& current_input_method_id) {
  std::vector<std::string>::const_iterator iter =
      std::find(input_method_ids.begin(),
                input_method_ids.end(),
                current_input_method_id);
  if (iter != input_method_ids.end())
    ++iter;
  if (iter == input_method_ids.end())
    iter = input_method_ids.begin();
  ChangeInputMethodInternal(*iter, true);
}

InputMethodDescriptor InputMethodManagerImpl::GetCurrentInputMethod() const {
  if (current_input_method_.id().empty())
    return InputMethodUtil::GetFallbackInputMethodDescriptor();

  return current_input_method_;
}

InputMethodPropertyList
InputMethodManagerImpl::GetCurrentInputMethodProperties() const {
  // This check is necessary since an IME property (e.g. for Pinyin) might be
  // sent from ibus-daemon AFTER the current input method is switched to XKB.
  if (InputMethodUtil::IsKeyboardLayout(GetCurrentInputMethod().id()))
    return InputMethodPropertyList();  // Empty list.
  return property_list_;
}

void InputMethodManagerImpl::SetCurrentInputMethodProperties(
    const InputMethodPropertyList& property_list) {
  property_list_ = property_list;
  PropertyChanged();
}

XKeyboard* InputMethodManagerImpl::GetXKeyboard() {
  return xkeyboard_.get();
}

InputMethodUtil* InputMethodManagerImpl::GetInputMethodUtil() {
  return &util_;
}

ComponentExtensionIMEManager*
    InputMethodManagerImpl::GetComponentExtensionIMEManager() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return component_extension_ime_manager_.get();
}

void InputMethodManagerImpl::InitializeComponentExtension() {
  ComponentExtensionIMEManagerImpl* impl =
      new ComponentExtensionIMEManagerImpl();
  scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(impl);
  impl->InitializeAsync(base::Bind(
                       &InputMethodManagerImpl::OnComponentExtensionInitialized,
                       weak_ptr_factory_.GetWeakPtr(),
                       base::Passed(&delegate)));
}

void InputMethodManagerImpl::Init(base::SequencedTaskRunner* ui_task_runner) {
  DCHECK(thread_checker_.CalledOnValidThread());

  xkeyboard_.reset(XKeyboard::Create());

  // We can't call impl->Initialize here, because file thread is not available
  // at this moment.
  ui_task_runner->PostTask(
      FROM_HERE,
      base::Bind(&InputMethodManagerImpl::InitializeComponentExtension,
                 weak_ptr_factory_.GetWeakPtr()));
}

void InputMethodManagerImpl::SetCandidateWindowControllerForTesting(
    CandidateWindowController* candidate_window_controller) {
  candidate_window_controller_.reset(candidate_window_controller);
  candidate_window_controller_->AddObserver(this);
}

void InputMethodManagerImpl::SetXKeyboardForTesting(XKeyboard* xkeyboard) {
  xkeyboard_.reset(xkeyboard);
}

void InputMethodManagerImpl::InitializeComponentExtensionForTesting(
    scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
  OnComponentExtensionInitialized(delegate.Pass());
}

void InputMethodManagerImpl::PropertyChanged() {
  FOR_EACH_OBSERVER(InputMethodManager::Observer,
                    observers_,
                    InputMethodPropertyChanged(this));
}

void InputMethodManagerImpl::CandidateClicked(int index) {
  IBusEngineHandlerInterface* engine =
      IBusBridge::Get()->GetCurrentEngineHandler();
  if (engine)
    engine->CandidateClicked(index);
}

void InputMethodManagerImpl::CandidateWindowOpened() {
  FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
                    candidate_window_observers_,
                    CandidateWindowOpened(this));
}

void InputMethodManagerImpl::CandidateWindowClosed() {
  FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
                    candidate_window_observers_,
                    CandidateWindowClosed(this));
}

void InputMethodManagerImpl::OnScreenLocked() {
  saved_previous_input_method_ = previous_input_method_;
  saved_current_input_method_ = current_input_method_;
  saved_active_input_method_ids_ = active_input_method_ids_;

  const std::string hardware_keyboard_id = util_.GetHardwareInputMethodId();
  // We'll add the hardware keyboard if it's not included in
  // |active_input_method_list| so that the user can always use the hardware
  // keyboard on the screen locker.
  bool should_add_hardware_keyboard = true;

  active_input_method_ids_.clear();
  for (size_t i = 0; i < saved_active_input_method_ids_.size(); ++i) {
    const std::string& input_method_id = saved_active_input_method_ids_[i];
    // Skip if it's not a keyboard layout. Drop input methods including
    // extension ones.
    if (!IsLoginKeyboard(input_method_id))
      continue;
    active_input_method_ids_.push_back(input_method_id);
    if (input_method_id == hardware_keyboard_id)
      should_add_hardware_keyboard = false;
  }
  if (should_add_hardware_keyboard)
    active_input_method_ids_.push_back(hardware_keyboard_id);

  ChangeInputMethod(current_input_method_.id());
}

void InputMethodManagerImpl::OnScreenUnlocked() {
  previous_input_method_ = saved_previous_input_method_;
  current_input_method_ = saved_current_input_method_;
  active_input_method_ids_ = saved_active_input_method_ids_;

  ChangeInputMethod(current_input_method_.id());
}

bool InputMethodManagerImpl::InputMethodIsActivated(
    const std::string& input_method_id) {
  return Contains(active_input_method_ids_, input_method_id);
}

bool InputMethodManagerImpl::ContainsOnlyKeyboardLayout(
    const std::vector<std::string>& value) {
  for (size_t i = 0; i < value.size(); ++i) {
    if (!InputMethodUtil::IsKeyboardLayout(value[i]))
      return false;
  }
  return true;
}

void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() {
  if (candidate_window_controller_.get())
    return;

  candidate_window_controller_.reset(
      CandidateWindowController::CreateCandidateWindowController());
  candidate_window_controller_->AddObserver(this);
}

}  // namespace input_method
}  // namespace chromeos
