// Copyright 2017 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.

#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/logging/counters.h"
#include "src/numbers/conversions.h"
#include "src/objects/objects-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
#endif

namespace v8 {
namespace internal {

BUILTIN(BigIntConstructor) {
  HandleScope scope(isolate);
  if (!args.new_target()->IsUndefined(isolate)) {  // [[Construct]]
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kNotConstructor,
                              isolate->factory()->BigInt_string()));
  }
  // [[Call]]
  Handle<Object> value = args.atOrUndefined(isolate, 1);

  if (value->IsJSReceiver()) {
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, value,
        JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(value),
                                ToPrimitiveHint::kNumber));
  }

  if (value->IsNumber()) {
    RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromNumber(isolate, value));
  } else {
    RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromObject(isolate, value));
  }
}

BUILTIN(BigIntAsUintN) {
  HandleScope scope(isolate);
  Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);

  Handle<Object> bits;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, bits,
      Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));

  Handle<BigInt> bigint;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
                                     BigInt::FromObject(isolate, bigint_obj));

  RETURN_RESULT_OR_FAILURE(isolate,
                           BigInt::AsUintN(isolate, bits->Number(), bigint));
}

BUILTIN(BigIntAsIntN) {
  HandleScope scope(isolate);
  Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);

  Handle<Object> bits;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, bits,
      Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));

  Handle<BigInt> bigint;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
                                     BigInt::FromObject(isolate, bigint_obj));

  return *BigInt::AsIntN(isolate, bits->Number(), bigint);
}

namespace {

MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value,
                                    const char* caller) {
  // 1. If Type(value) is BigInt, return value.
  if (value->IsBigInt()) return Handle<BigInt>::cast(value);
  // 2. If Type(value) is Object and value has a [[BigIntData]] internal slot:
  if (value->IsJSPrimitiveWrapper()) {
    // 2a. Assert: value.[[BigIntData]] is a BigInt value.
    // 2b. Return value.[[BigIntData]].
    Object data = JSPrimitiveWrapper::cast(*value).value();
    if (data.IsBigInt()) return handle(BigInt::cast(data), isolate);
  }
  // 3. Throw a TypeError exception.
  THROW_NEW_ERROR(
      isolate,
      NewTypeError(MessageTemplate::kNotGeneric,
                   isolate->factory()->NewStringFromAsciiChecked(caller),
                   isolate->factory()->NewStringFromStaticChars("BigInt")),
      BigInt);
}

Object BigIntToStringImpl(Handle<Object> receiver, Handle<Object> radix,
                          Isolate* isolate, const char* builtin_name) {
  // 1. Let x be ? thisBigIntValue(this value).
  Handle<BigInt> x;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, x, ThisBigIntValue(isolate, receiver, builtin_name));
  // 2. If radix is not present, let radixNumber be 10.
  // 3. Else if radix is undefined, let radixNumber be 10.
  int radix_number = 10;
  if (!radix->IsUndefined(isolate)) {
    // 4. Else, let radixNumber be ? ToInteger(radix).
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
                                       Object::ToInteger(isolate, radix));
    double radix_double = radix->Number();
    // 5. If radixNumber < 2 or radixNumber > 36, throw a RangeError exception.
    if (radix_double < 2 || radix_double > 36) {
      THROW_NEW_ERROR_RETURN_FAILURE(
          isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
    }
    radix_number = static_cast<int>(radix_double);
  }
  // Return the String representation of this Number value using the radix
  // specified by radixNumber.
  RETURN_RESULT_OR_FAILURE(isolate, BigInt::ToString(isolate, x, radix_number));
}

}  // namespace

BUILTIN(BigIntPrototypeToLocaleString) {
  HandleScope scope(isolate);
#ifdef V8_INTL_SUPPORT
  if (FLAG_harmony_intl_bigint) {
    // 1. Let x be ? thisBigIntValue(this value).
    Handle<BigInt> x;
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, x,
        ThisBigIntValue(isolate, args.receiver(),
                        "BigInt.prototype.toLocaleString"));

    RETURN_RESULT_OR_FAILURE(
        isolate,
        Intl::NumberToLocaleString(isolate, x, args.atOrUndefined(isolate, 1),
                                   args.atOrUndefined(isolate, 2)));
  }
  // Fallbacks to old toString implemention if flag is off or no
  // V8_INTL_SUPPORT
#endif  // V8_INTL_SUPPORT
  Handle<Object> radix = isolate->factory()->undefined_value();
  return BigIntToStringImpl(args.receiver(), radix, isolate,
                            "BigInt.prototype.toLocaleString");
}

BUILTIN(BigIntPrototypeToString) {
  HandleScope scope(isolate);
  Handle<Object> radix = args.atOrUndefined(isolate, 1);
  return BigIntToStringImpl(args.receiver(), radix, isolate,
                            "BigInt.prototype.toString");
}

BUILTIN(BigIntPrototypeValueOf) {
  HandleScope scope(isolate);
  RETURN_RESULT_OR_FAILURE(
      isolate,
      ThisBigIntValue(isolate, args.receiver(), "BigInt.prototype.valueOf"));
}

}  // namespace internal
}  // namespace v8
