// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif  // V8_INTL_SUPPORT

#include "src/objects/js-collator.h"

#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/objects/js-collator-inl.h"
#include "unicode/coll.h"
#include "unicode/locid.h"
#include "unicode/strenum.h"
#include "unicode/ucol.h"
#include "unicode/uloc.h"

namespace v8 {
namespace internal {

namespace {

// TODO(gsathya): Consider internalizing the value strings.
void CreateDataPropertyForOptions(Isolate* isolate, Handle<JSObject> options,
                                  Handle<String> key, const char* value) {
  CHECK_NOT_NULL(value);
  Handle<String> value_str =
      isolate->factory()->NewStringFromAsciiChecked(value);

  // This is a brand new JSObject that shouldn't already have the same
  // key so this shouldn't fail.
  CHECK(JSReceiver::CreateDataProperty(isolate, options, key, value_str,
                                       kDontThrow)
            .FromJust());
}

void CreateDataPropertyForOptions(Isolate* isolate, Handle<JSObject> options,
                                  Handle<String> key, bool value) {
  Handle<Object> value_obj = isolate->factory()->ToBoolean(value);

  // This is a brand new JSObject that shouldn't already have the same
  // key so this shouldn't fail.
  CHECK(JSReceiver::CreateDataProperty(isolate, options, key, value_obj,
                                       kDontThrow)
            .FromJust());
}

}  // anonymous namespace

// static
Handle<JSObject> JSCollator::ResolvedOptions(Isolate* isolate,
                                             Handle<JSCollator> collator) {
  Handle<JSObject> options =
      isolate->factory()->NewJSObject(isolate->object_function());

  JSCollator::Usage usage = collator->usage();
  CreateDataPropertyForOptions(isolate, options,
                               isolate->factory()->usage_string(),
                               JSCollator::UsageToString(usage));

  icu::Collator* icu_collator = collator->icu_collator()->raw();
  CHECK_NOT_NULL(icu_collator);

  UErrorCode status = U_ZERO_ERROR;
  bool numeric =
      icu_collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON;
  CHECK(U_SUCCESS(status));
  CreateDataPropertyForOptions(isolate, options,
                               isolate->factory()->numeric_string(), numeric);

  const char* case_first = nullptr;
  status = U_ZERO_ERROR;
  switch (icu_collator->getAttribute(UCOL_CASE_FIRST, status)) {
    case UCOL_LOWER_FIRST:
      case_first = "lower";
      break;
    case UCOL_UPPER_FIRST:
      case_first = "upper";
      break;
    default:
      case_first = "false";
  }
  CHECK(U_SUCCESS(status));
  CreateDataPropertyForOptions(
      isolate, options, isolate->factory()->caseFirst_string(), case_first);

  const char* sensitivity = nullptr;
  status = U_ZERO_ERROR;
  switch (icu_collator->getAttribute(UCOL_STRENGTH, status)) {
    case UCOL_PRIMARY: {
      CHECK(U_SUCCESS(status));
      status = U_ZERO_ERROR;
      // case level: true + s1 -> case, s1 -> base.
      if (UCOL_ON == icu_collator->getAttribute(UCOL_CASE_LEVEL, status)) {
        sensitivity = "case";
      } else {
        sensitivity = "base";
      }
      CHECK(U_SUCCESS(status));
      break;
    }
    case UCOL_SECONDARY:
      sensitivity = "accent";
      break;
    case UCOL_TERTIARY:
      sensitivity = "variant";
      break;
    case UCOL_QUATERNARY:
      // We shouldn't get quaternary and identical from ICU, but if we do
      // put them into variant.
      sensitivity = "variant";
      break;
    default:
      sensitivity = "variant";
  }
  CHECK(U_SUCCESS(status));
  CreateDataPropertyForOptions(
      isolate, options, isolate->factory()->sensitivity_string(), sensitivity);

  status = U_ZERO_ERROR;
  bool ignore_punctuation = icu_collator->getAttribute(UCOL_ALTERNATE_HANDLING,
                                                       status) == UCOL_SHIFTED;
  CHECK(U_SUCCESS(status));
  CreateDataPropertyForOptions(isolate, options,
                               isolate->factory()->ignorePunctuation_string(),
                               ignore_punctuation);

  status = U_ZERO_ERROR;
  const char* collation;
  std::unique_ptr<icu::StringEnumeration> collation_values(
      icu_collator->getKeywordValues("co", status));
  // Collation wasn't provided as a keyword to icu, use default.
  if (status == U_ILLEGAL_ARGUMENT_ERROR) {
    CreateDataPropertyForOptions(
        isolate, options, isolate->factory()->collation_string(), "default");
  } else {
    CHECK(U_SUCCESS(status));
    CHECK_NOT_NULL(collation_values.get());

    int32_t length;
    status = U_ZERO_ERROR;
    collation = collation_values->next(&length, status);
    CHECK(U_SUCCESS(status));

    // There has to be at least one value.
    CHECK_NOT_NULL(collation);
    CreateDataPropertyForOptions(
        isolate, options, isolate->factory()->collation_string(), collation);

    status = U_ZERO_ERROR;
    collation_values->reset(status);
    CHECK(U_SUCCESS(status));
  }

  status = U_ZERO_ERROR;
  icu::Locale icu_locale = icu_collator->getLocale(ULOC_VALID_LOCALE, status);
  CHECK(U_SUCCESS(status));

  char result[ULOC_FULLNAME_CAPACITY];
  status = U_ZERO_ERROR;
  uloc_toLanguageTag(icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY,
                     FALSE, &status);
  CHECK(U_SUCCESS(status));

  CreateDataPropertyForOptions(isolate, options,
                               isolate->factory()->locale_string(), result);

  return options;
}

namespace {

std::map<std::string, std::string> LookupUnicodeExtensions(
    const icu::Locale& icu_locale, const std::set<std::string>& relevant_keys) {
  std::map<std::string, std::string> extensions;

  UErrorCode status = U_ZERO_ERROR;
  std::unique_ptr<icu::StringEnumeration> keywords(
      icu_locale.createKeywords(status));
  if (U_FAILURE(status)) return extensions;

  if (!keywords) return extensions;
  char value[ULOC_FULLNAME_CAPACITY];

  int32_t length;
  status = U_ZERO_ERROR;
  for (const char* keyword = keywords->next(&length, status);
       keyword != nullptr; keyword = keywords->next(&length, status)) {
    // Ignore failures in ICU and skip to the next keyword.
    //
    // This is fine.™
    if (U_FAILURE(status)) {
      status = U_ZERO_ERROR;
      continue;
    }

    icu_locale.getKeywordValue(keyword, value, ULOC_FULLNAME_CAPACITY, status);

    // Ignore failures in ICU and skip to the next keyword.
    //
    // This is fine.™
    if (U_FAILURE(status)) {
      status = U_ZERO_ERROR;
      continue;
    }

    const char* bcp47_key = uloc_toUnicodeLocaleKey(keyword);

    // Ignore keywords that we don't recognize - spec allows that.
    if (bcp47_key && (relevant_keys.find(bcp47_key) != relevant_keys.end())) {
      const char* bcp47_value = uloc_toUnicodeLocaleType(bcp47_key, value);
      extensions.insert(
          std::pair<std::string, std::string>(bcp47_key, bcp47_value));
    }
  }

  return extensions;
}

void SetCaseFirstOption(icu::Collator* icu_collator, const char* value) {
  CHECK_NOT_NULL(icu_collator);
  CHECK_NOT_NULL(value);
  UErrorCode status = U_ZERO_ERROR;
  if (strcmp(value, "upper") == 0) {
    icu_collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
  } else if (strcmp(value, "lower") == 0) {
    icu_collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
  } else {
    icu_collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
  }
  CHECK(U_SUCCESS(status));
}

}  // anonymous namespace

// static
MaybeHandle<JSCollator> JSCollator::InitializeCollator(
    Isolate* isolate, Handle<JSCollator> collator, Handle<Object> locales,
    Handle<Object> options_obj) {
  // 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  Handle<JSObject> requested_locales;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, requested_locales,
                             Intl::CanonicalizeLocaleListJS(isolate, locales),
                             JSCollator);

  // 2. If options is undefined, then
  if (options_obj->IsUndefined(isolate)) {
    // 2. a. Let options be ObjectCreate(null).
    options_obj = isolate->factory()->NewJSObjectWithNullProto();
  } else {
    // 3. Else
    // 3. a. Let options be ? ToObject(options).
    ASSIGN_RETURN_ON_EXCEPTION(
        isolate, options_obj,
        Object::ToObject(isolate, options_obj, "Intl.Collator"), JSCollator);
  }

  // At this point, options_obj can either be a JSObject or a JSProxy only.
  Handle<JSReceiver> options = Handle<JSReceiver>::cast(options_obj);

  // 4. Let usage be ? GetOption(options, "usage", "string", « "sort",
  // "search" », "sort").
  std::vector<const char*> values = {"sort", "search"};
  std::unique_ptr<char[]> usage_str = nullptr;
  JSCollator::Usage usage = JSCollator::Usage::SORT;
  Maybe<bool> found_usage = Intl::GetStringOption(
      isolate, options, "usage", values, "Intl.Collator", &usage_str);
  MAYBE_RETURN(found_usage, MaybeHandle<JSCollator>());

  if (found_usage.FromJust()) {
    DCHECK_NOT_NULL(usage_str.get());
    if (strcmp(usage_str.get(), "search") == 0) {
      usage = JSCollator::Usage::SEARCH;
    }
  }

  // 5. Set collator.[[Usage]] to usage.
  collator->set_usage(usage);

  // 6. If usage is "sort", then
  //    a. Let localeData be %Collator%.[[SortLocaleData]].
  // 7. Else,
  //    a. Let localeData be %Collator%.[[SearchLocaleData]].
  //
  // The above two spec operations aren't required, the Intl spec is
  // crazy. See https://github.com/tc39/ecma402/issues/256

  // TODO(gsathya): This is currently done as part of the
  // Intl::ResolveLocale call below. Fix this once resolveLocale is
  // changed to not do the lookup.
  //
  // 9. Let matcher be ? GetOption(options, "localeMatcher", "string",
  // « "lookup", "best fit" », "best fit").
  // 10. Set opt.[[localeMatcher]] to matcher.

  // 11. Let numeric be ? GetOption(options, "numeric", "boolean",
  // undefined, undefined).
  // 12. If numeric is not undefined, then
  //    a. Let numeric be ! ToString(numeric).
  //
  // Note: We omit the ToString(numeric) operation as it's not
  // observable. Intl::GetBoolOption returns a Boolean and
  // ToString(Boolean) is not side-effecting.
  //
  // 13. Set opt.[[kn]] to numeric.
  bool numeric;
  Maybe<bool> found_numeric = Intl::GetBoolOption(isolate, options, "numeric",
                                                  "Intl.Collator", &numeric);
  MAYBE_RETURN(found_numeric, MaybeHandle<JSCollator>());

  // 14. Let caseFirst be ? GetOption(options, "caseFirst", "string",
  //     « "upper", "lower", "false" », undefined).
  // 15. Set opt.[[kf]] to caseFirst.
  values = {"upper", "lower", "false"};
  std::unique_ptr<char[]> case_first_str = nullptr;
  Maybe<bool> found_case_first = Intl::GetStringOption(
      isolate, options, "caseFirst", values, "Intl.Collator", &case_first_str);
  MAYBE_RETURN(found_case_first, MaybeHandle<JSCollator>());

  // The relevant unicode extensions accepted by Collator as specified here:
  // https://tc39.github.io/ecma402/#sec-intl-collator-internal-slots
  //
  // 16. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]].
  std::set<std::string> relevant_extension_keys{"co", "kn", "kf"};

  // We don't pass the relevant_extension_keys to ResolveLocale here
  // as per the spec.
  //
  // In ResolveLocale, the spec makes sure we only pick and use the
  // relevant extension keys and ignore any other keys. Also, in
  // ResolveLocale, the spec makes sure that if a given key has both a
  // value in the options object and an unicode extension value, then
  // we pick the value provided in the options object.
  // For example: in the case of `new Intl.Collator('en-u-kn-true', {
  // numeric: false })` the value `false` is used for the `numeric`
  // key.
  //
  // Instead of performing all this validation in ResolveLocale, we
  // just perform it inline below. In the future when we port
  // ResolveLocale to C++, we can make all these validations generic
  // and move it ResolveLocale.
  //
  // 17. Let r be ResolveLocale(%Collator%.[[AvailableLocales]],
  // requestedLocales, opt, %Collator%.[[RelevantExtensionKeys]],
  // localeData).
  // 18. Set collator.[[Locale]] to r.[[locale]].
  Handle<JSObject> r;
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, r,
      Intl::ResolveLocale(isolate, "collator", requested_locales, options),
      JSCollator);

  Handle<String> locale_with_extension_str =
      isolate->factory()->NewStringFromStaticChars("localeWithExtension");
  Handle<Object> locale_with_extension_obj =
      JSObject::GetDataProperty(r, locale_with_extension_str);

  // The locale_with_extension has to be a string. Either a user
  // provided canonicalized string or the default locale.
  CHECK(locale_with_extension_obj->IsString());
  Handle<String> locale_with_extension =
      Handle<String>::cast(locale_with_extension_obj);

  icu::Locale icu_locale =
      Intl::CreateICULocale(isolate, locale_with_extension);
  DCHECK(!icu_locale.isBogus());

  std::map<std::string, std::string> extensions =
      LookupUnicodeExtensions(icu_locale, relevant_extension_keys);

  // 19. Let collation be r.[[co]].
  //
  // r.[[co]] is already set as part of the icu::Locale creation as
  // icu parses unicode extensions and sets the keywords.
  //
  // We need to sanitize the keywords based on certain ECMAScript rules.
  //
  // As per https://tc39.github.io/ecma402/#sec-intl-collator-internal-slots:
  // The values "standard" and "search" must not be used as elements
  // in any [[SortLocaleData]][locale].co and
  // [[SearchLocaleData]][locale].co list.
  auto co_extension_it = extensions.find("co");
  if (co_extension_it != extensions.end()) {
    const std::string& value = co_extension_it->second;
    if ((value == "search") || (value == "standard")) {
      UErrorCode status = U_ZERO_ERROR;
      icu_locale.setKeywordValue("co", NULL, status);
      CHECK(U_SUCCESS(status));
    }
  }

  // 20. If collation is null, let collation be "default".
  // 21. Set collator.[[Collation]] to collation.
  //
  // We don't store the collation value as per the above two steps
  // here. The collation value can be looked up from icu::Collator on
  // demand, as part of Intl.Collator.prototype.resolvedOptions.

  UErrorCode status = U_ZERO_ERROR;
  std::unique_ptr<icu::Collator> icu_collator(
      icu::Collator::createInstance(icu_locale, status));
  if (U_FAILURE(status) || icu_collator.get() == nullptr) {
    status = U_ZERO_ERROR;
    // Remove extensions and try again.
    icu::Locale no_extension_locale(icu_locale.getBaseName());
    icu_collator.reset(
        icu::Collator::createInstance(no_extension_locale, status));

    if (U_FAILURE(status) || icu_collator.get() == nullptr) {
      FATAL("Failed to create ICU collator, are ICU data files missing?");
    }
  }
  DCHECK(U_SUCCESS(status));
  CHECK_NOT_NULL(icu_collator.get());

  // 22. If relevantExtensionKeys contains "kn", then
  //     a. Set collator.[[Numeric]] to ! SameValue(r.[[kn]], "true").
  //
  // If the numeric value is passed in through the options object,
  // then we use it. Otherwise, we check if the numeric value is
  // passed in through the unicode extensions.
  status = U_ZERO_ERROR;
  if (found_numeric.FromJust()) {
    icu_collator->setAttribute(UCOL_NUMERIC_COLLATION,
                               numeric ? UCOL_ON : UCOL_OFF, status);
    CHECK(U_SUCCESS(status));
  } else {
    auto kn_extension_it = extensions.find("kn");
    if (kn_extension_it != extensions.end()) {
      const std::string& value = kn_extension_it->second;

      numeric = (value == "true");

      icu_collator->setAttribute(UCOL_NUMERIC_COLLATION,
                                 numeric ? UCOL_ON : UCOL_OFF, status);
      CHECK(U_SUCCESS(status));
    }
  }

  // 23. If relevantExtensionKeys contains "kf", then
  //     a. Set collator.[[CaseFirst]] to r.[[kf]].
  //
  // If the caseFirst value is passed in through the options object,
  // then we use it. Otherwise, we check if the caseFirst value is
  // passed in through the unicode extensions.
  if (found_case_first.FromJust()) {
    const char* case_first_cstr = case_first_str.get();
    SetCaseFirstOption(icu_collator.get(), case_first_cstr);
  } else {
    auto kf_extension_it = extensions.find("kf");
    if (kf_extension_it != extensions.end()) {
      const std::string& value = kf_extension_it->second;
      SetCaseFirstOption(icu_collator.get(), value.c_str());
    }
  }

  // Normalization is always on, by the spec. We are free to optimize
  // if the strings are already normalized (but we don't have a way to tell
  // that right now).
  status = U_ZERO_ERROR;
  icu_collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
  CHECK(U_SUCCESS(status));

  // 24. Let sensitivity be ? GetOption(options, "sensitivity",
  // "string", « "base", "accent", "case", "variant" », undefined).
  values = {"base", "accent", "case", "variant"};
  std::unique_ptr<char[]> sensitivity_str = nullptr;
  Maybe<bool> found_sensitivity =
      Intl::GetStringOption(isolate, options, "sensitivity", values,
                            "Intl.Collator", &sensitivity_str);
  MAYBE_RETURN(found_sensitivity, MaybeHandle<JSCollator>());

  // 25. If sensitivity is undefined, then
  if (!found_sensitivity.FromJust()) {
    // 25. a. If usage is "sort", then
    if (usage == Usage::SORT) {
      // 25. a. i. Let sensitivity be "variant".
      // 26. Set collator.[[Sensitivity]] to sensitivity.
      icu_collator->setStrength(icu::Collator::TERTIARY);
    }
  } else {
    DCHECK(found_sensitivity.FromJust());
    const char* sensitivity_cstr = sensitivity_str.get();
    DCHECK_NOT_NULL(sensitivity_cstr);

    // 26. Set collator.[[Sensitivity]] to sensitivity.
    if (strcmp(sensitivity_cstr, "base") == 0) {
      icu_collator->setStrength(icu::Collator::PRIMARY);
    } else if (strcmp(sensitivity_cstr, "accent") == 0) {
      icu_collator->setStrength(icu::Collator::SECONDARY);
    } else if (strcmp(sensitivity_cstr, "case") == 0) {
      icu_collator->setStrength(icu::Collator::PRIMARY);
      status = U_ZERO_ERROR;
      icu_collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
      CHECK(U_SUCCESS(status));
    } else {
      DCHECK_EQ(0, strcmp(sensitivity_cstr, "variant"));
      icu_collator->setStrength(icu::Collator::TERTIARY);
    }
  }

  // 27.Let ignorePunctuation be ? GetOption(options,
  // "ignorePunctuation", "boolean", undefined, false).
  bool ignore_punctuation;
  Maybe<bool> found_ignore_punctuation =
      Intl::GetBoolOption(isolate, options, "ignorePunctuation",
                          "Intl.Collator", &ignore_punctuation);
  MAYBE_RETURN(found_ignore_punctuation, MaybeHandle<JSCollator>());

  // 28. Set collator.[[IgnorePunctuation]] to ignorePunctuation.
  if (found_ignore_punctuation.FromJust() && ignore_punctuation) {
    status = U_ZERO_ERROR;
    icu_collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
    CHECK(U_SUCCESS(status));
  }

  Handle<Managed<icu::Collator>> managed_collator =
      Managed<icu::Collator>::FromUniquePtr(isolate, 0,
                                            std::move(icu_collator));
  collator->set_icu_collator(*managed_collator);

  // 29. Return collator.
  return collator;
}

// static
const char* JSCollator::UsageToString(Usage usage) {
  switch (usage) {
    case Usage::SORT:
      return "sort";
    case Usage::SEARCH:
      return "search";
    case Usage::COUNT:
      UNREACHABLE();
  }
}

}  // namespace internal
}  // namespace v8
