// Copyright 2019 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 <memory>
#include <vector>

#include "src/objects/js-display-names-inl.h"
#include "src/objects/js-display-names.h"

#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/objects/intl-objects.h"
#include "src/objects/managed.h"
#include "src/objects/objects-inl.h"

#include "unicode/dtfmtsym.h"
#include "unicode/dtptngen.h"
#include "unicode/localebuilder.h"
#include "unicode/locdspnm.h"
#include "unicode/timezone.h"
#include "unicode/tznames.h"
#include "unicode/uloc.h"
#include "unicode/unistr.h"
#include "unicode/uscript.h"

namespace v8 {
namespace internal {

namespace {
// Type: identifying the types of the display names.
//
// ecma402/#sec-properties-of-intl-displaynames-instances
enum class Type {
  kUndefined,
  kLanguage,
  kRegion,
  kScript,
  kCurrency,
  kWeekday,
  kMonth,
  kQuarter,
  kDayPeriod,
  kDateTimeField
};

bool IsUnicodeScriptSubtag(const std::string& value) {
  UErrorCode status = U_ZERO_ERROR;
  icu::LocaleBuilder builder;
  builder.setScript(value).build(status);
  return U_SUCCESS(status);
}

bool IsUnicodeRegionSubtag(const std::string& value) {
  UErrorCode status = U_ZERO_ERROR;
  icu::LocaleBuilder builder;
  builder.setRegion(value).build(status);
  return U_SUCCESS(status);
}

UDisplayContext ToUDisplayContext(JSDisplayNames::Style style) {
  switch (style) {
    case JSDisplayNames::Style::kLong:
      return UDISPCTX_LENGTH_FULL;
    case JSDisplayNames::Style::kShort:
    case JSDisplayNames::Style::kNarrow:
      return UDISPCTX_LENGTH_SHORT;
  }
}

}  // anonymous namespace

// Abstract class for all different types.
class DisplayNamesInternal {
 public:
  DisplayNamesInternal() = default;
  virtual ~DisplayNamesInternal() = default;
  virtual const char* type() const = 0;
  virtual icu::Locale locale() const = 0;
  virtual Maybe<icu::UnicodeString> of(Isolate* isolate,
                                       const char* code) const = 0;
  virtual const char* calendar() const { return nullptr; }
};

namespace {

class LocaleDisplayNamesCommon : public DisplayNamesInternal {
 public:
  LocaleDisplayNamesCommon(const icu::Locale& locale,
                           JSDisplayNames::Style style, bool fallback)
      : style_(style) {
    UDisplayContext sub =
        fallback ? UDISPCTX_SUBSTITUTE : UDISPCTX_NO_SUBSTITUTE;
    UDisplayContext display_context[] = {ToUDisplayContext(style_),
                                         UDISPCTX_DIALECT_NAMES,
                                         UDISPCTX_CAPITALIZATION_NONE, sub};
    ldn_.reset(
        icu::LocaleDisplayNames::createInstance(locale, display_context, 4));
  }

  ~LocaleDisplayNamesCommon() override = default;

  icu::Locale locale() const override { return ldn_->getLocale(); }

 protected:
  icu::LocaleDisplayNames* locale_display_names() const { return ldn_.get(); }

 private:
  std::unique_ptr<icu::LocaleDisplayNames> ldn_;
  JSDisplayNames::Style style_;
};

class LanguageNames : public LocaleDisplayNamesCommon {
 public:
  LanguageNames(const icu::Locale& locale, JSDisplayNames::Style style,
                bool fallback)
      : LocaleDisplayNamesCommon(locale, style, fallback) {}
  ~LanguageNames() override = default;
  const char* type() const override { return "language"; }
  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    UErrorCode status = U_ZERO_ERROR;
    icu::Locale l =
        icu::Locale(icu::Locale::forLanguageTag(code, status).getBaseName());
    std::string checked = l.toLanguageTag<std::string>(status);

    if (U_FAILURE(status)) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }

    icu::UnicodeString result;
    locale_display_names()->localeDisplayName(checked.c_str(), result);

    return Just(result);
  }
};

class RegionNames : public LocaleDisplayNamesCommon {
 public:
  RegionNames(const icu::Locale& locale, JSDisplayNames::Style style,
              bool fallback)
      : LocaleDisplayNamesCommon(locale, style, fallback) {}
  ~RegionNames() override = default;
  const char* type() const override { return "region"; }
  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    std::string code_str(code);
    if (!IsUnicodeRegionSubtag(code_str)) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }

    icu::UnicodeString result;
    locale_display_names()->regionDisplayName(code_str.c_str(), result);
    return Just(result);
  }
};

class ScriptNames : public LocaleDisplayNamesCommon {
 public:
  ScriptNames(const icu::Locale& locale, JSDisplayNames::Style style,
              bool fallback)
      : LocaleDisplayNamesCommon(locale, style, fallback) {}
  ~ScriptNames() override = default;
  const char* type() const override { return "script"; }
  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    std::string code_str(code);
    if (!IsUnicodeScriptSubtag(code_str)) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }

    icu::UnicodeString result;
    locale_display_names()->scriptDisplayName(code_str.c_str(), result);
    return Just(result);
  }
};

class CurrencyNames : public LocaleDisplayNamesCommon {
 public:
  CurrencyNames(const icu::Locale& locale, JSDisplayNames::Style style,
                bool fallback)
      : LocaleDisplayNamesCommon(locale, style, fallback) {}
  ~CurrencyNames() override = default;
  const char* type() const override { return "currency"; }
  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    std::string code_str(code);
    if (!Intl::IsWellFormedCurrency(code_str)) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }

    icu::UnicodeString result;
    locale_display_names()->keyValueDisplayName("currency", code_str.c_str(),
                                                result);

    return Just(result);
  }
};

UDateTimePGDisplayWidth StyleToUDateTimePGDisplayWidth(
    JSDisplayNames::Style style) {
  switch (style) {
    case JSDisplayNames::Style::kLong:
      return UDATPG_WIDE;
    case JSDisplayNames::Style::kShort:
      return UDATPG_ABBREVIATED;
    case JSDisplayNames::Style::kNarrow:
      return UDATPG_NARROW;
  }
}

UDateTimePatternField StringToUDateTimePatternField(const char* code) {
  switch (code[0]) {
    case 'd':
      if (strcmp(code, "day") == 0) return UDATPG_DAY_FIELD;
      if (strcmp(code, "dayPeriod") == 0) return UDATPG_DAYPERIOD_FIELD;
      break;
    case 'e':
      if (strcmp(code, "era") == 0) return UDATPG_ERA_FIELD;
      break;
    case 'h':
      if (strcmp(code, "hour") == 0) return UDATPG_HOUR_FIELD;
      break;
    case 'm':
      if (strcmp(code, "minute") == 0) return UDATPG_MINUTE_FIELD;
      if (strcmp(code, "month") == 0) return UDATPG_MONTH_FIELD;
      break;
    case 'q':
      if (strcmp(code, "quarter") == 0) return UDATPG_QUARTER_FIELD;
      break;
    case 's':
      if (strcmp(code, "second") == 0) return UDATPG_SECOND_FIELD;
      break;
    case 't':
      if (strcmp(code, "timeZoneName") == 0) return UDATPG_ZONE_FIELD;
      break;
    case 'w':
      if (strcmp(code, "weekOfYear") == 0) return UDATPG_WEEK_OF_YEAR_FIELD;
      if (strcmp(code, "weekday") == 0) return UDATPG_WEEKDAY_FIELD;
      break;
    case 'y':
      if (strcmp(code, "year") == 0) return UDATPG_YEAR_FIELD;
      break;
    default:
      break;
  }
  UNREACHABLE();
}

class DateTimeFieldNames : public DisplayNamesInternal {
 public:
  DateTimeFieldNames(const icu::Locale& locale, JSDisplayNames::Style style)
      : locale_(locale), width_(StyleToUDateTimePGDisplayWidth(style)) {
    UErrorCode status = U_ZERO_ERROR;
    generator_.reset(
        icu::DateTimePatternGenerator::createInstance(locale_, status));
    DCHECK(U_SUCCESS(status));
  }
  ~DateTimeFieldNames() override = default;
  const char* type() const override { return "dateTimeField"; }
  icu::Locale locale() const override { return locale_; }
  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    UDateTimePatternField field = StringToUDateTimePatternField(code);
    if (field == UDATPG_FIELD_COUNT) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }
    return Just(generator_->getFieldDisplayName(field, width_));
  }

 private:
  icu::Locale locale_;
  UDateTimePGDisplayWidth width_;
  std::unique_ptr<icu::DateTimePatternGenerator> generator_;
};

icu::DateFormatSymbols::DtWidthType StyleToDtWidthType(
    JSDisplayNames::Style style, Type type) {
  switch (style) {
    case JSDisplayNames::Style::kLong:
      return icu::DateFormatSymbols::WIDE;
    case JSDisplayNames::Style::kShort:
      return icu::DateFormatSymbols::SHORT;
    case JSDisplayNames::Style::kNarrow:
      if (type == Type::kQuarter) {
        return icu::DateFormatSymbols::ABBREVIATED;
      } else {
        return icu::DateFormatSymbols::NARROW;
      }
  }
}

class DateFormatSymbolsNames : public DisplayNamesInternal {
 public:
  DateFormatSymbolsNames(const char* type, const icu::Locale& locale,
                         const icu::UnicodeString* array, int32_t length,
                         const char* calendar)
      : type_(type),
        locale_(locale),
        array_(array),
        length_(length),
        calendar_(calendar) {}

  ~DateFormatSymbolsNames() override = default;

  const char* type() const override { return type_; }

  icu::Locale locale() const override { return locale_; }

  const char* calendar() const override {
    if (calendar_.empty()) {
      return nullptr;
    }
    return calendar_.c_str();
  }

  virtual int32_t ComputeIndex(const char* code) const = 0;

  Maybe<icu::UnicodeString> of(Isolate* isolate,
                               const char* code) const override {
    int32_t index = ComputeIndex(code);
    if (index < 0 || index >= length_) {
      THROW_NEW_ERROR_RETURN_VALUE(
          isolate, NewRangeError(MessageTemplate::kInvalidArgument),
          Nothing<icu::UnicodeString>());
    }
    return Just(array_[index]);
  }

 private:
  const char* type_;
  icu::Locale locale_;
  const icu::UnicodeString* array_;
  int32_t length_;
  std::string calendar_;
};

class WeekdayNames : public DateFormatSymbolsNames {
 public:
  WeekdayNames(const char* type, const icu::Locale& locale,
               const icu::UnicodeString* array, int32_t length,
               const char* calendar)
      : DateFormatSymbolsNames(type, locale, array, length, calendar) {}
  ~WeekdayNames() override = default;

  int32_t ComputeIndex(const char* code) const override {
    int32_t i = atoi(code);
    if (i == 7) return 1;
    if (i > 0 && i < 7) return i + 1;
    return -1;
  }
};

class MonthNames : public DateFormatSymbolsNames {
 public:
  MonthNames(const char* type, const icu::Locale& locale,
             const icu::UnicodeString* array, int32_t length,
             const char* calendar)
      : DateFormatSymbolsNames(type, locale, array, length, calendar) {}
  ~MonthNames() override = default;

  int32_t ComputeIndex(const char* code) const override {
    return atoi(code) - 1;
  }
};

class QuarterNames : public DateFormatSymbolsNames {
 public:
  QuarterNames(const char* type, const icu::Locale& locale,
               const icu::UnicodeString* array, int32_t length,
               const char* calendar)
      : DateFormatSymbolsNames(type, locale, array, length, calendar) {}
  ~QuarterNames() override = default;

  int32_t ComputeIndex(const char* code) const override {
    return atoi(code) - 1;
  }
};

class DayPeriodNames : public DateFormatSymbolsNames {
 public:
  DayPeriodNames(const char* type, const icu::Locale& locale,
                 const icu::UnicodeString* array, int32_t length,
                 const char* calendar)
      : DateFormatSymbolsNames(type, locale, array, length, calendar) {}
  ~DayPeriodNames() override = default;

  int32_t ComputeIndex(const char* code) const override {
    if (strcmp("am", code) == 0) {
      return 0;
    } else if (strcmp("pm", code) == 0) {
      return 1;
    } else {
      return -1;
    }
  }
};

const char* gWeekday = "weekday";
const char* gMonth = "month";
const char* gQuarter = "quarter";
const char* gDayPeriod = "dayPeriod";

DateFormatSymbolsNames* CreateDateFormatSymbolsNames(
    const icu::Locale& locale, JSDisplayNames::Style style, Type type) {
  UErrorCode status = U_ZERO_ERROR;
  std::unique_ptr<icu::DateFormatSymbols> symbols(
      icu::DateFormatSymbols::createForLocale(locale, status));
  if (U_FAILURE(status)) {
    return nullptr;
  }
  icu::DateFormatSymbols::DtWidthType width_type =
      StyleToDtWidthType(style, type);
  int32_t count = 0;
  std::string calendar =
      locale.getUnicodeKeywordValue<std::string>("ca", status);

  switch (type) {
    case Type::kMonth:
      return new MonthNames(
          gMonth, locale,
          symbols->getMonths(count, icu::DateFormatSymbols::STANDALONE,
                             width_type),
          count, calendar.c_str());
    case Type::kWeekday:
      return new WeekdayNames(
          gWeekday, locale,
          symbols->getWeekdays(count, icu::DateFormatSymbols::STANDALONE,
                               width_type),
          count, calendar.c_str());
    case Type::kQuarter:
      return new QuarterNames(
          gQuarter, locale,
          symbols->getQuarters(count, icu::DateFormatSymbols::STANDALONE,
                               width_type),
          count, calendar.c_str());
    case Type::kDayPeriod:
      return new DayPeriodNames(gDayPeriod, locale,
                                symbols->getAmPmStrings(count), count,
                                calendar.c_str());
    default:
      UNREACHABLE();
  }
}

DisplayNamesInternal* CreateInternal(const icu::Locale& locale,
                                     JSDisplayNames::Style style, Type type,
                                     bool fallback) {
  switch (type) {
    case Type::kLanguage:
      return new LanguageNames(locale, style, fallback);
    case Type::kRegion:
      return new RegionNames(locale, style, fallback);
    case Type::kScript:
      return new ScriptNames(locale, style, fallback);
    case Type::kCurrency:
      return new CurrencyNames(locale, style, fallback);
    case Type::kDateTimeField:
      return new DateTimeFieldNames(locale, style);
    case Type::kMonth:
    case Type::kWeekday:
    case Type::kQuarter:
    case Type::kDayPeriod:
      return CreateDateFormatSymbolsNames(locale, style, type);
    default:
      UNREACHABLE();
  }
}

}  // anonymous namespace

// ecma402 #sec-Intl.DisplayNames
MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
                                                Handle<Map> map,
                                                Handle<Object> locales,
                                                Handle<Object> input_options) {
  const char* service = "Intl.DisplayNames";
  Factory* factory = isolate->factory();

  Handle<JSReceiver> options;
  // 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  Maybe<std::vector<std::string>> maybe_requested_locales =
      Intl::CanonicalizeLocaleList(isolate, locales);
  MAYBE_RETURN(maybe_requested_locales, Handle<JSDisplayNames>());
  std::vector<std::string> requested_locales =
      maybe_requested_locales.FromJust();

  // 4. Let options be ? ToObject(options).
  ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
                             Object::ToObject(isolate, input_options),
                             JSDisplayNames);

  // Note: No need to create a record. It's not observable.
  // 5. Let opt be a new Record.

  // 6. Let localeData be %DisplayNames%.[[LocaleData]].

  // 7. Let matcher be ? GetOption(options, "localeMatcher", "string", «
  // "lookup", "best fit" », "best fit").
  Maybe<Intl::MatcherOption> maybe_locale_matcher =
      Intl::GetLocaleMatcher(isolate, options, "Intl.DisplayNames");
  MAYBE_RETURN(maybe_locale_matcher, MaybeHandle<JSDisplayNames>());

  // 8. Set opt.[[localeMatcher]] to matcher.
  Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();

  std::unique_ptr<char[]> calendar_str = nullptr;
  if (FLAG_harmony_intl_displaynames_date_types) {
    const std::vector<const char*> empty_values = {};
    // Let calendar be ? GetOption(options, "calendar",
    //    "string", undefined, undefined).
    Maybe<bool> maybe_calendar = Intl::GetStringOption(
        isolate, options, "calendar", empty_values, service, &calendar_str);
    MAYBE_RETURN(maybe_calendar, MaybeHandle<JSDisplayNames>());
    // If calendar is not undefined, then
    if (maybe_calendar.FromJust() && calendar_str != nullptr) {
      // a. If calendar does not match the (3*8alphanum) *("-" (3*8alphanum))
      //    sequence, throw a RangeError exception.
      if (!Intl::IsWellFormedCalendar(calendar_str.get())) {
        THROW_NEW_ERROR(
            isolate,
            NewRangeError(
                MessageTemplate::kInvalid, factory->calendar_string(),
                factory->NewStringFromAsciiChecked(calendar_str.get())),
            JSDisplayNames);
      }
    }
  }

  // Set opt.[[ca]] to calendar.

  // ecma402/#sec-Intl.DisplayNames-internal-slots
  // The value of the [[RelevantExtensionKeys]] internal slot is
  // « "ca" ».
  std::set<std::string> relevant_extension_keys_ca = {"ca"};
  std::set<std::string> relevant_extension_keys = {};
  // 9. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]],
  //     requestedLocales, opt, %DisplayNames%.[[RelevantExtensionKeys]]).
  Maybe<Intl::ResolvedLocale> maybe_resolve_locale = Intl::ResolveLocale(
      isolate, JSDisplayNames::GetAvailableLocales(), requested_locales,
      matcher,
      FLAG_harmony_intl_displaynames_date_types ? relevant_extension_keys_ca
                                                : relevant_extension_keys);
  if (maybe_resolve_locale.IsNothing()) {
    THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
                    JSDisplayNames);
  }
  Intl::ResolvedLocale r = maybe_resolve_locale.FromJust();

  icu::Locale icu_locale = r.icu_locale;
  UErrorCode status = U_ZERO_ERROR;
  if (calendar_str != nullptr &&
      Intl::IsValidCalendar(icu_locale, calendar_str.get())) {
    icu_locale.setUnicodeKeywordValue("ca", calendar_str.get(), status);
    DCHECK(U_SUCCESS(status));
  }

  // 10. Let s be ? GetOption(options, "style", "string",
  //                          «"long", "short", "narrow"», "long").
  Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
      isolate, options, "style", "Intl.DisplayNames",
      {"long", "short", "narrow"},
      {Style::kLong, Style::kShort, Style::kNarrow}, Style::kLong);
  MAYBE_RETURN(maybe_style, MaybeHandle<JSDisplayNames>());
  Style style_enum = maybe_style.FromJust();

  // 11. Set displayNames.[[Style]] to style.

  // 12. Let type be ? GetOption(options, "type", "string", « "language",
  //     "region", "script", "currency", "weekday", "month", "quarter",
  //     "dayPeriod", "dateTimeField" », undefined).
  Maybe<Type> maybe_type =
      FLAG_harmony_intl_displaynames_date_types
          ? Intl::GetStringOption<Type>(
                isolate, options, "type", "Intl.DisplayNames",
                {"language", "region", "script", "currency", "weekday", "month",
                 "quarter", "dayPeriod", "dateTimeField"},
                {
                    Type::kLanguage,
                    Type::kRegion,
                    Type::kScript,
                    Type::kCurrency,
                    Type::kWeekday,
                    Type::kMonth,
                    Type::kQuarter,
                    Type::kDayPeriod,
                    Type::kDateTimeField,
                },
                Type::kUndefined)
          : Intl::GetStringOption<Type>(
                isolate, options, "type", "Intl.DisplayNames",
                {"language", "region", "script", "currency"},
                {
                    Type::kLanguage,
                    Type::kRegion,
                    Type::kScript,
                    Type::kCurrency,
                },
                Type::kUndefined);
  MAYBE_RETURN(maybe_type, MaybeHandle<JSDisplayNames>());
  Type type_enum = maybe_type.FromJust();

  // 13. If type is undefined, throw a TypeError exception.
  if (type_enum == Type::kUndefined) {
    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidArgument),
                    JSDisplayNames);
  }

  // 14. Set displayNames.[[Type]] to type.

  // 15. Let fallback be ? GetOption(options, "fallback", "string",
  //     « "code", "none" », "code").
  Maybe<Fallback> maybe_fallback = Intl::GetStringOption<Fallback>(
      isolate, options, "fallback", "Intl.DisplayNames", {"code", "none"},
      {Fallback::kCode, Fallback::kNone}, Fallback::kCode);
  MAYBE_RETURN(maybe_fallback, MaybeHandle<JSDisplayNames>());
  Fallback fallback_enum = maybe_fallback.FromJust();

  // 16. Set displayNames.[[Fallback]] to fallback.

  // 17. Set displayNames.[[Locale]] to the value of r.[[Locale]].

  // Let calendar be r.[[ca]].

  // Set displayNames.[[Calendar]] to calendar.

  // Let dataLocale be r.[[dataLocale]].

  // Let dataLocaleData be localeData.[[<dataLocale>]].

  // Let types be dataLocaleData.[[types]].

  // Assert: types is a Record (see 1.3.3).

  // Let typeFields be types.[[<type>]].

  // Assert: typeFields is a Record (see 1.3.3).

  // Let styleFields be typeFields.[[<style>]].

  // Assert: styleFields is a Record (see 1.3.3).

  // Set displayNames.[[Fields]] to styleFields.

  DisplayNamesInternal* internal = CreateInternal(
      icu_locale, style_enum, type_enum, fallback_enum == Fallback::kCode);
  if (internal == nullptr) {
    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIcuError),
                    JSDisplayNames);
  }

  Handle<Managed<DisplayNamesInternal>> managed_internal =
      Managed<DisplayNamesInternal>::FromRawPtr(isolate, 0, internal);

  Handle<JSDisplayNames> display_names =
      Handle<JSDisplayNames>::cast(factory->NewFastOrSlowJSObjectFromMap(map));
  display_names->set_flags(0);
  display_names->set_style(style_enum);
  display_names->set_fallback(fallback_enum);

  DisallowHeapAllocation no_gc;
  display_names->set_internal(*managed_internal);

  // Return displayNames.
  return display_names;
}

// ecma402 #sec-Intl.DisplayNames.prototype.resolvedOptions
Handle<JSObject> JSDisplayNames::ResolvedOptions(
    Isolate* isolate, Handle<JSDisplayNames> display_names) {
  Factory* factory = isolate->factory();
  // 4. Let options be ! ObjectCreate(%ObjectPrototype%).
  Handle<JSObject> options = factory->NewJSObject(isolate->object_function());

  DisplayNamesInternal* internal = display_names->internal().raw();

  Maybe<std::string> maybe_locale = Intl::ToLanguageTag(internal->locale());
  DCHECK(maybe_locale.IsJust());
  Handle<String> locale = isolate->factory()->NewStringFromAsciiChecked(
      maybe_locale.FromJust().c_str());
  Handle<String> style = display_names->StyleAsString();
  Handle<String> type = factory->NewStringFromAsciiChecked(internal->type());
  Handle<String> fallback = display_names->FallbackAsString();

  Maybe<bool> maybe_create_locale = JSReceiver::CreateDataProperty(
      isolate, options, factory->locale_string(), locale, Just(kDontThrow));
  DCHECK(maybe_create_locale.FromJust());
  USE(maybe_create_locale);
  if (internal->calendar() != nullptr) {
    Maybe<bool> maybe_create_calendar = JSReceiver::CreateDataProperty(
        isolate, options, factory->calendar_string(),
        factory->NewStringFromAsciiChecked(internal->calendar()),
        Just(kDontThrow));
    DCHECK(maybe_create_calendar.FromJust());
    USE(maybe_create_calendar);
  }
  Maybe<bool> maybe_create_style = JSReceiver::CreateDataProperty(
      isolate, options, factory->style_string(), style, Just(kDontThrow));
  DCHECK(maybe_create_style.FromJust());
  USE(maybe_create_style);

  Maybe<bool> maybe_create_type = JSReceiver::CreateDataProperty(
      isolate, options, factory->type_string(), type, Just(kDontThrow));
  DCHECK(maybe_create_type.FromJust());
  USE(maybe_create_type);

  Maybe<bool> maybe_create_fallback = JSReceiver::CreateDataProperty(
      isolate, options, factory->fallback_string(), fallback, Just(kDontThrow));
  DCHECK(maybe_create_fallback.FromJust());
  USE(maybe_create_fallback);

  return options;
}

// ecma402 #sec-Intl.DisplayNames.prototype.of
MaybeHandle<Object> JSDisplayNames::Of(Isolate* isolate,
                                       Handle<JSDisplayNames> display_names,
                                       Handle<Object> code_obj) {
  Handle<String> code;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, code, Object::ToString(isolate, code_obj),
                             Object);
  DisplayNamesInternal* internal = display_names->internal().raw();
  Maybe<icu::UnicodeString> maybe_result =
      internal->of(isolate, code->ToCString().get());
  MAYBE_RETURN(maybe_result, Handle<Object>());
  icu::UnicodeString result = maybe_result.FromJust();
  if (result.isBogus()) {
    return isolate->factory()->undefined_value();
  }
  return Intl::ToString(isolate, result).ToHandleChecked();
}

namespace {

struct CheckCalendar {
  static const char* key() { return "calendar"; }
  static const char* path() { return nullptr; }
};

}  // namespace

const std::set<std::string>& JSDisplayNames::GetAvailableLocales() {
  static base::LazyInstance<Intl::AvailableLocales<CheckCalendar>>::type
      available_locales = LAZY_INSTANCE_INITIALIZER;
  return available_locales.Pointer()->Get();
}

Handle<String> JSDisplayNames::StyleAsString() const {
  switch (style()) {
    case Style::kLong:
      return GetReadOnlyRoots().long_string_handle();
    case Style::kShort:
      return GetReadOnlyRoots().short_string_handle();
    case Style::kNarrow:
      return GetReadOnlyRoots().narrow_string_handle();
  }
  UNREACHABLE();
}

Handle<String> JSDisplayNames::FallbackAsString() const {
  switch (fallback()) {
    case Fallback::kCode:
      return GetReadOnlyRoots().code_string_handle();
    case Fallback::kNone:
      return GetReadOnlyRoots().none_string_handle();
  }
  UNREACHABLE();
}

}  // namespace internal
}  // namespace v8
