// 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_persistence.h"

#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/sys_info.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"

namespace chromeos {
namespace input_method {
namespace {

void PersistSystemInputMethod(const std::string& input_method) {
  if (!g_browser_process || !g_browser_process->local_state())
    return;

  g_browser_process->local_state()->SetString(
        language_prefs::kPreferredKeyboardLayout, input_method);
}

// Update user LRU keyboard layout for login screen
static void SetUserLRUInputMethod(
    const std::string& input_method,
    const chromeos::input_method::InputMethodManager* const manager) {
  // Skip if it's not a keyboard layout. Drop input methods including
  // extension ones.
  if (!manager->IsLoginKeyboard(input_method))
    return;

  PrefService* const local_state = g_browser_process->local_state();

  Profile* const profile = ProfileManager::GetDefaultProfile();

  if (profile == NULL)
    return;

  if (!manager->IsLoginKeyboard(input_method))
    return;

  const std::string username = profile->GetProfileName();
  if (base::SysInfo::IsRunningOnChromeOS() && !username.empty() &&
      !local_state->ReadOnly()) {
    bool update_succeed = false;
    {
      // Updater may have side-effects, therefore we do not replace
      // entry while updater exists.
      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
      base::DictionaryValue* const users_lru_input_methods = updater.Get();
      if (users_lru_input_methods) {
        users_lru_input_methods->SetStringWithoutPathExpansion(username,
                                                               input_method);
        update_succeed = true;
      }
    }
    if (!update_succeed) {
      // Somehow key kUsersLRUInputMethod has value of invalid type.
      // Replace and retry.
      local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue());

      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
      base::DictionaryValue* const users_lru_input_methods = updater.Get();
      if (users_lru_input_methods) {
        users_lru_input_methods->SetStringWithoutPathExpansion(username,
                                                               input_method);
        update_succeed = true;
      }
    }
    if (!update_succeed) {
      DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '"
               << prefs::kUsersLRUInputMethod << "' for '" << username << "'";
    }
  }
}

void PersistUserInputMethod(const std::string& input_method,
                            InputMethodManager* const manager) {
  PrefService* user_prefs = NULL;
  Profile* profile = ProfileManager::GetDefaultProfile();
  if (profile)
    user_prefs = profile->GetPrefs();
  if (!user_prefs)
    return;

  SetUserLRUInputMethod(input_method, manager);

  const std::string current_input_method_on_pref =
      user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
  if (current_input_method_on_pref == input_method)
    return;

  user_prefs->SetString(prefs::kLanguagePreviousInputMethod,
                        current_input_method_on_pref);
  user_prefs->SetString(prefs::kLanguageCurrentInputMethod,
                        input_method);
}

}  // namespace

InputMethodPersistence::InputMethodPersistence(
    InputMethodManager* input_method_manager)
    : input_method_manager_(input_method_manager),
      state_(InputMethodManager::STATE_LOGIN_SCREEN) {
  input_method_manager_->AddObserver(this);
}

InputMethodPersistence::~InputMethodPersistence() {
  input_method_manager_->RemoveObserver(this);
}

void InputMethodPersistence::InputMethodChanged(
    InputMethodManager* manager, bool show_message) {
  DCHECK_EQ(input_method_manager_, manager);
  const std::string current_input_method =
      manager->GetCurrentInputMethod().id();
  // Save the new input method id depending on the current browser state.
  switch (state_) {
    case InputMethodManager::STATE_LOGIN_SCREEN:
      if (!manager->IsLoginKeyboard(current_input_method)) {
        DVLOG(1) << "Only keyboard layouts are supported: "
                 << current_input_method;
        return;
      }
      PersistSystemInputMethod(current_input_method);
      return;
    case InputMethodManager::STATE_BROWSER_SCREEN:
      PersistUserInputMethod(current_input_method, manager);
      return;
    case InputMethodManager::STATE_LOCK_SCREEN:
      // We use a special set of input methods on the screen. Do not update.
      return;
    case InputMethodManager::STATE_TERMINATING:
      return;
  }
  NOTREACHED();
}

void InputMethodPersistence::InputMethodPropertyChanged(
    InputMethodManager* manager) {}

void InputMethodPersistence::OnSessionStateChange(
    InputMethodManager::State new_state) {
  state_ = new_state;
}

}  // namespace input_method
}  // namespace chromeos
