// 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/ui/webui/options/language_options_handler_common.h"

#include <stddef.h>

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/translate/translate_service.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "components/translate/core/browser/translate_prefs.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/l10n/l10n_util.h"

using base::UserMetricsAction;

namespace options {

LanguageOptionsHandlerCommon::LanguageOptionsHandlerCommon() {
}

LanguageOptionsHandlerCommon::~LanguageOptionsHandlerCommon() {
}

void LanguageOptionsHandlerCommon::GetLocalizedValues(
    base::DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

#if defined(OS_CHROMEOS)
  const int product_id = IDS_PRODUCT_OS_NAME;
#else
  const int product_id = IDS_PRODUCT_NAME;
#endif

  static OptionsStringResource resources[] = {
    { "addButton", IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON },
    { "languages", IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES },
    { "addLanguageInstructions",
      IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS },
    { "cannotBeDisplayedInThisLanguage",
      IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
      product_id },
    { "isDisplayedInThisLanguage",
      IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
      product_id },
    { "displayInThisLanguage",
      IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
      product_id },
    { "restartRequired", IDS_OPTIONS_RELAUNCH_REQUIRED },
  // OS X uses the OS native spellchecker so no need for these strings.
#if !defined(OS_MACOSX)
    { "useThisForSpellChecking",
      IDS_OPTIONS_SETTINGS_USE_THIS_FOR_SPELL_CHECKING },
    { "cannotBeUsedForSpellChecking",
      IDS_OPTIONS_SETTINGS_CANNOT_BE_USED_FOR_SPELL_CHECKING },
    { "enableSpellCheck", IDS_OPTIONS_ENABLE_SPELLCHECK },
    { "downloadingDictionary", IDS_OPTIONS_DICTIONARY_DOWNLOADING },
    { "downloadFailed", IDS_OPTIONS_DICTIONARY_DOWNLOAD_FAILED },
    { "retryButton", IDS_OPTIONS_DICTIONARY_DOWNLOAD_RETRY },
    { "downloadFailHelp", IDS_OPTIONS_DICTIONARY_DOWNLOAD_FAIL_HELP },
#endif  // !OS_MACOSX
    { "addLanguageTitle", IDS_OPTIONS_LANGUAGES_ADD_TITLE },
    { "addLanguageSelectLabel", IDS_OPTIONS_LANGUAGES_ADD_SELECT_LABEL },
    { "restartButton", IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON },
    { "offerToTranslateInThisLanguage",
      IDS_OPTIONS_LANGUAGES_OFFER_TO_TRANSLATE_IN_THIS_LANGUAGE },
    { "cannotTranslateInThisLanguage",
      IDS_OPTIONS_LANGUAGES_CANNOT_TRANSLATE_IN_THIS_LANGUAGE },
  };

  RegisterStrings(localized_strings, resources, arraysize(resources));

  // The following are resources, rather than local strings.
  std::string application_locale = g_browser_process->GetApplicationLocale();
  localized_strings->SetString("currentUiLanguageCode", application_locale);
  std::string prospective_locale =
      g_browser_process->local_state()->GetString(prefs::kApplicationLocale);
  localized_strings->SetString("prospectiveUiLanguageCode",
      !prospective_locale.empty() ? prospective_locale : application_locale);
  localized_strings->Set("spellCheckLanguageCodeSet",
                         GetSpellCheckLanguageCodeSet());
  localized_strings->Set("uiLanguageCodeSet", GetUILanguageCodeSet());

  Profile* profile = Profile::FromWebUI(web_ui());
  PrefService* prefs = profile->GetPrefs();
  std::string default_target_language =
      TranslateService::GetTargetLanguage(prefs);
  localized_strings->SetString("defaultTargetLanguage",
                               default_target_language);

  std::vector<std::string> languages;
  translate::TranslateDownloadManager::GetSupportedLanguages(&languages);

  base::ListValue* languages_list = new base::ListValue();
  for (std::vector<std::string>::iterator it = languages.begin();
       it != languages.end(); ++it) {
    languages_list->AppendString(*it);
  }

  localized_strings->Set("translateSupportedLanguages", languages_list);
}

void LanguageOptionsHandlerCommon::Uninitialize() {
  SpellcheckService* service = GetSpellcheckService();
  if (!service)
    return;

  for (const auto& dict : service->GetHunspellDictionaries())
    dict->RemoveObserver(this);
}

void LanguageOptionsHandlerCommon::RegisterMessages() {
  web_ui()->RegisterMessageCallback("languageOptionsOpen",
      base::Bind(
          &LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback,
          base::Unretained(this)));
  web_ui()->RegisterMessageCallback("spellCheckLanguageChange",
      base::Bind(
          &LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback,
          base::Unretained(this)));
  web_ui()->RegisterMessageCallback("uiLanguageChange",
      base::Bind(
          &LanguageOptionsHandlerCommon::UiLanguageChangeCallback,
          base::Unretained(this)));
  web_ui()->RegisterMessageCallback("retryDictionaryDownload",
      base::Bind(
          &LanguageOptionsHandlerCommon::RetrySpellcheckDictionaryDownload,
          base::Unretained(this)));
  web_ui()->RegisterMessageCallback("updateLanguageList",
      base::Bind(
          &LanguageOptionsHandlerCommon::UpdateLanguageListCallback,
          base::Unretained(this)));
}

void LanguageOptionsHandlerCommon::OnHunspellDictionaryInitialized(
    const std::string& language) {
}

void LanguageOptionsHandlerCommon::OnHunspellDictionaryDownloadBegin(
    const std::string& language) {
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.LanguageOptions.onDictionaryDownloadBegin",
      base::Value(language));
}

void LanguageOptionsHandlerCommon::OnHunspellDictionaryDownloadSuccess(
    const std::string& language) {
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.LanguageOptions.onDictionaryDownloadSuccess",
      base::Value(language));
}

void LanguageOptionsHandlerCommon::OnHunspellDictionaryDownloadFailure(
    const std::string& language) {
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.LanguageOptions.onDictionaryDownloadFailure",
      base::Value(language));
}

base::DictionaryValue* LanguageOptionsHandlerCommon::GetUILanguageCodeSet() {
  base::DictionaryValue* dictionary = new base::DictionaryValue();
  const std::vector<std::string>& available_locales =
      l10n_util::GetAvailableLocales();
  for (size_t i = 0; i < available_locales.size(); ++i)
    dictionary->SetBoolean(available_locales[i], true);
  return dictionary;
}

base::DictionaryValue*
LanguageOptionsHandlerCommon::GetSpellCheckLanguageCodeSet() {
  base::DictionaryValue* dictionary = new base::DictionaryValue();
  std::vector<std::string> spell_check_languages;
  spellcheck::SpellCheckLanguages(&spell_check_languages);
  for (size_t i = 0; i < spell_check_languages.size(); ++i) {
    dictionary->SetBoolean(spell_check_languages[i], true);
  }
  return dictionary;
}

void LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback(
    const base::ListValue* args) {
  base::RecordAction(UserMetricsAction("LanguageOptions_Open"));
  SpellcheckService* service = GetSpellcheckService();
  if (!service)
    return;

  for (const auto& dictionary : service->GetHunspellDictionaries()) {
    dictionary->RemoveObserver(this);
    dictionary->AddObserver(this);

    if (dictionary->IsDownloadInProgress())
      OnHunspellDictionaryDownloadBegin(dictionary->GetLanguage());
    else if (dictionary->IsDownloadFailure())
      OnHunspellDictionaryDownloadFailure(dictionary->GetLanguage());
    else
      OnHunspellDictionaryDownloadSuccess(dictionary->GetLanguage());
  }
}

void LanguageOptionsHandlerCommon::UiLanguageChangeCallback(
    const base::ListValue* args) {
  const std::string language_code =
      base::UTF16ToASCII(ExtractStringValue(args));
  CHECK(!language_code.empty());
  const std::string action = base::StringPrintf(
      "LanguageOptions_UiLanguageChange_%s", language_code.c_str());
  base::RecordComputedAction(action);
  SetApplicationLocale(language_code);
  base::Value language_value(language_code);
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.LanguageOptions.uiLanguageSaved", language_value);
}

void LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback(
    const base::ListValue* args) {
  const std::string language_code =
      base::UTF16ToASCII(ExtractStringValue(args));
  const std::string action = base::StringPrintf(
      "LanguageOptions_SpellCheckLanguageChange_%s", language_code.c_str());
  base::RecordComputedAction(action);

  SpellcheckService* service = GetSpellcheckService();
  if (!service)
    return;

  for (const auto& dictionary : service->GetHunspellDictionaries()) {
    dictionary->RemoveObserver(this);
    dictionary->AddObserver(this);
  }
}

void LanguageOptionsHandlerCommon::UpdateLanguageListCallback(
    const base::ListValue* args) {
  CHECK_EQ(args->GetSize(), 1u);
  const base::ListValue* language_list;
  args->GetList(0, &language_list);
  DCHECK(language_list);

  std::vector<std::string> languages;
  for (base::ListValue::const_iterator it = language_list->begin();
       it != language_list->end(); ++it) {
    std::string lang;
    it->GetAsString(&lang);
    languages.push_back(lang);
  }

  Profile* profile = Profile::FromWebUI(web_ui());
  std::unique_ptr<translate::TranslatePrefs> translate_prefs =
      ChromeTranslateClient::CreateTranslatePrefs(profile->GetPrefs());
  translate_prefs->UpdateLanguageList(languages);
}

void LanguageOptionsHandlerCommon::RetrySpellcheckDictionaryDownload(
    const base::ListValue* args) {
  std::string language = base::UTF16ToUTF8(ExtractStringValue(args));
  SpellcheckService* service = GetSpellcheckService();
  if (!service)
    return;

  for (const auto& dictionary : service->GetHunspellDictionaries()) {
    if (dictionary->GetLanguage() == language) {
      dictionary->RetryDownloadDictionary(
          Profile::FromWebUI(web_ui())->GetRequestContext());
      return;
    }
  }
}

SpellcheckService* LanguageOptionsHandlerCommon::GetSpellcheckService() {
  return SpellcheckServiceFactory::GetForContext(Profile::FromWebUI(web_ui()));
}

}  // namespace options
