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

#include "src/objects/intl-objects.h"
#include "src/objects/js-break-iterator-inl.h"
#include "unicode/brkiter.h"

namespace v8 {
namespace internal {

MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::New(
    Isolate* isolate, Handle<Map> map, Handle<Object> locales,
    Handle<Object> options_obj) {
  Factory* factory = isolate->factory();

  // 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  Maybe<std::vector<std::string>> maybe_requested_locales =
      Intl::CanonicalizeLocaleList(isolate, locales);
  MAYBE_RETURN(maybe_requested_locales, MaybeHandle<JSV8BreakIterator>());
  std::vector<std::string> requested_locales =
      maybe_requested_locales.FromJust();

  Handle<JSReceiver> options;
  if (options_obj->IsUndefined(isolate)) {
    options = factory->NewJSObjectWithNullProto();
  } else {
    ASSIGN_RETURN_ON_EXCEPTION(
        isolate, options,
        Object::ToObject(isolate, options_obj, "Intl.JSV8BreakIterator"),
        JSV8BreakIterator);
  }

  // Extract locale string
  Maybe<Intl::MatcherOption> maybe_locale_matcher =
      Intl::GetLocaleMatcher(isolate, options, "Intl.JSV8BreakIterator");
  MAYBE_RETURN(maybe_locale_matcher, MaybeHandle<JSV8BreakIterator>());
  Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();

  Intl::ResolvedLocale r =
      Intl::ResolveLocale(isolate, JSV8BreakIterator::GetAvailableLocales(),
                          requested_locales, matcher, {});

  // Extract type from options
  Maybe<Type> maybe_type = Intl::GetStringOption<Type>(
      isolate, options, "type", "Intl.v8BreakIterator",
      {"word", "character", "sentence", "line"},
      {Type::WORD, Type::CHARACTER, Type::SENTENCE, Type::LINE}, Type::WORD);
  MAYBE_RETURN(maybe_type, MaybeHandle<JSV8BreakIterator>());
  Type type_enum = maybe_type.FromJust();

  icu::Locale icu_locale = r.icu_locale;
  DCHECK(!icu_locale.isBogus());

  // Construct break_iterator using icu_locale and type
  UErrorCode status = U_ZERO_ERROR;
  std::unique_ptr<icu::BreakIterator> break_iterator = nullptr;
  switch (type_enum) {
    case Type::CHARACTER:
      break_iterator.reset(
          icu::BreakIterator::createCharacterInstance(icu_locale, status));
      break;
    case Type::SENTENCE:
      break_iterator.reset(
          icu::BreakIterator::createSentenceInstance(icu_locale, status));
      break;
    case Type::LINE:
      break_iterator.reset(
          icu::BreakIterator::createLineInstance(icu_locale, status));
      break;
    default:
      break_iterator.reset(
          icu::BreakIterator::createWordInstance(icu_locale, status));
      break;
  }

  // Error handling for break_iterator
  if (U_FAILURE(status)) {
    FATAL("Failed to create ICU break iterator, are ICU data files missing?");
  }
  CHECK_NOT_NULL(break_iterator.get());
  isolate->CountUsage(v8::Isolate::UseCounterFeature::kBreakIterator);

  // Construct managed objects from pointers
  Handle<Managed<icu::BreakIterator>> managed_break_iterator =
      Managed<icu::BreakIterator>::FromUniquePtr(isolate, 0,
                                                 std::move(break_iterator));
  Handle<Managed<icu::UnicodeString>> managed_unicode_string =
      Managed<icu::UnicodeString>::FromRawPtr(isolate, 0, nullptr);

  Handle<String> locale_str =
      isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());

  // Now all properties are ready, so we can allocate the result object.
  Handle<JSV8BreakIterator> break_iterator_holder =
      Handle<JSV8BreakIterator>::cast(
          isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
  DisallowHeapAllocation no_gc;
  break_iterator_holder->set_locale(*locale_str);
  break_iterator_holder->set_type(type_enum);
  break_iterator_holder->set_break_iterator(*managed_break_iterator);
  break_iterator_holder->set_unicode_string(*managed_unicode_string);

  // Return break_iterator_holder
  return break_iterator_holder;
}

Handle<JSObject> JSV8BreakIterator::ResolvedOptions(
    Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
  Factory* factory = isolate->factory();

  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
  Handle<String> locale(break_iterator->locale(), isolate);

  JSObject::AddProperty(isolate, result, factory->locale_string(), locale,
                        NONE);
  JSObject::AddProperty(isolate, result, factory->type_string(),
                        break_iterator->TypeAsString(), NONE);
  return result;
}

void JSV8BreakIterator::AdoptText(
    Isolate* isolate, Handle<JSV8BreakIterator> break_iterator_holder,
    Handle<String> text) {
  icu::BreakIterator* break_iterator =
      break_iterator_holder->break_iterator().raw();
  CHECK_NOT_NULL(break_iterator);
  Handle<Managed<icu::UnicodeString>> unicode_string =
      Intl::SetTextToBreakIterator(isolate, text, break_iterator);
  break_iterator_holder->set_unicode_string(*unicode_string);
}

Handle<String> JSV8BreakIterator::TypeAsString() const {
  switch (type()) {
    case Type::CHARACTER:
      return GetReadOnlyRoots().character_string_handle();
    case Type::WORD:
      return GetReadOnlyRoots().word_string_handle();
    case Type::SENTENCE:
      return GetReadOnlyRoots().sentence_string_handle();
    case Type::LINE:
      return GetReadOnlyRoots().line_string_handle();
  }
  UNREACHABLE();
}

Handle<Object> JSV8BreakIterator::Current(
    Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
  return isolate->factory()->NewNumberFromInt(
      break_iterator->break_iterator().raw()->current());
}

Handle<Object> JSV8BreakIterator::First(
    Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
  return isolate->factory()->NewNumberFromInt(
      break_iterator->break_iterator().raw()->first());
}

Handle<Object> JSV8BreakIterator::Next(
    Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
  return isolate->factory()->NewNumberFromInt(
      break_iterator->break_iterator().raw()->next());
}

String JSV8BreakIterator::BreakType(Isolate* isolate,
                                    Handle<JSV8BreakIterator> break_iterator) {
  int32_t status = break_iterator->break_iterator().raw()->getRuleStatus();
  // Keep return values in sync with JavaScript BreakType enum.
  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
    return ReadOnlyRoots(isolate).none_string();
  }
  if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
    return ReadOnlyRoots(isolate).number_string();
  }
  if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
    return ReadOnlyRoots(isolate).letter_string();
  }
  if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
    return ReadOnlyRoots(isolate).kana_string();
  }
  if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
    return ReadOnlyRoots(isolate).ideo_string();
  }
  return ReadOnlyRoots(isolate).unknown_string();
}

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

}  // namespace internal
}  // namespace v8
