/*
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cobalt/script/mozjs/promise_wrapper.h"

#include "base/logging.h"
#include "third_party/mozjs/js/src/jsfun.h"

namespace cobalt {
namespace script {
namespace mozjs {
namespace {
enum ReservedSlots {
  kResolveFunction,
  kRejectFunction,
  kPromiseObject,
  kNumReservedSlots,
};

JSClass native_promise_class = {
    "NativePromise",  // name

    JSCLASS_HAS_RESERVED_SLOTS(kNumReservedSlots),  // flags

    JS_PropertyStub,        // addProperty
    JS_DeletePropertyStub,  // delProperty
    JS_PropertyStub,        // getProperty
    JS_StrictPropertyStub,  // setProperty
    JS_EnumerateStub,       // enumerate
    JS_ResolveStub,         // resolve
    JS_ConvertStub,         // convert
    NULL,                   // finalize
    NULL,                   // trace
};

JSBool NativeExecutor(JSContext* context, unsigned argc, JS::Value* vp) {
  // Get the resolve/reject functions from the call args.
  JS::CallArgs call_args = CallArgsFromVp(argc, vp);
  DCHECK_EQ(call_args.length(), 2);

  // Get the this object. Should be the native_promise object.
  JS::RootedValue this_value(context, call_args.computeThis(context));
  DCHECK(this_value.isObject());
  JS::RootedObject this_object(context, JSVAL_TO_OBJECT(this_value));
  DCHECK_EQ(JS_GetClass(this_object), &native_promise_class);

  // First argument is the resolve function. Second is the reject function.
  // Stash these in the reserved slots. Reserved slots get visited so there is
  // no need to define a special trace function.
  JS::RootedValue resolve_function_value(context, call_args.get(0));
  JS::RootedValue reject_function_value(context, call_args.get(1));
  DCHECK(resolve_function_value.isObject());
  DCHECK(JS_ObjectIsFunction(context, JSVAL_TO_OBJECT(resolve_function_value)));
  DCHECK(reject_function_value.isObject());
  DCHECK(JS_ObjectIsFunction(context, JSVAL_TO_OBJECT(reject_function_value)));

  JS_SetReservedSlot(this_object, kResolveFunction, resolve_function_value);
  JS_SetReservedSlot(this_object, kRejectFunction, reject_function_value);
  return true;
}

// Creates a new NativePromise object and initializes its reserved slots.
JSObject* CreateNativePromise(JSContext* context) {
  JS::RootedObject native_promise(
      context, JS_NewObject(context, &native_promise_class, NULL, NULL));
  DCHECK(native_promise);
  for (uint32_t i = 0; i < kNumReservedSlots; ++i) {
    JS_SetReservedSlot(native_promise, i, JS::NullHandleValue);
  }
  return native_promise;
}

// Create a new native function with the |native_promise| bound as |this|.
JSObject* CreateExecutorArgument(JSContext* context,
                                 JS::HandleObject native_promise) {
  JS::RootedObject executor_function(context);
  executor_function =
      JS_NewFunction(context, &NativeExecutor, 2, 0, NULL, NULL);
  DCHECK(executor_function);

  JS::RootedObject bound_executor(context);
  bound_executor = JS_BindCallable(context, executor_function, native_promise);
  DCHECK(bound_executor);
  return bound_executor;
}

// Get the Promise constructor from the global object.
JSObject* GetPromiseConstructor(JSContext* context,
                                JS::HandleObject global_object) {
  JS::RootedValue promise_constructor_property(context);
  JSBool result = JS_GetProperty(context, global_object, "Promise",
                                 promise_constructor_property.address());
  DCHECK(result);
  if (!promise_constructor_property.isObject() ||
      !JS_ObjectIsFunction(context,
                           JSVAL_TO_OBJECT(promise_constructor_property))) {
    DLOG(ERROR) << "\"Promise\" property is not a function.";
    return NULL;
  }
  return JSVAL_TO_OBJECT(promise_constructor_property);
}

void Settle(JSContext* context, JS::HandleValue result,
            JS::HandleObject resolver, ReservedSlots slot) {
  JS::RootedValue slot_value(context, JS_GetReservedSlot(resolver, slot));
  DCHECK(slot_value.isObject());
  DCHECK(JS_ObjectIsFunction(context, JSVAL_TO_OBJECT(slot_value)));

  JS::RootedValue return_value(context);
  const size_t kNumArguments = result.isUndefined() ? 0 : 1;
  JS::Value args[1] = {result};
  JSBool call_result =
      JS_CallFunctionValue(context, resolver, slot_value, kNumArguments, args,
                           return_value.address());
  if (!call_result) {
    DLOG(ERROR) << "Exception calling Promise function.";
    JS_ClearPendingException(context);
  }
}
}  // namespace

JSObject* PromiseWrapper::Create(JSContext* context,
                                 JS::HandleObject global_object) {
  // Get the Promise constructor.
  JS::RootedObject constructor(context,
                               GetPromiseConstructor(context, global_object));
  if (!constructor) {
    DLOG(ERROR) << "Failed to find Promise constructor.";
    return NULL;
  }
  // Create a new NativePromise JS object, and bind it to the NativeExecutor
  // function.
  JS::RootedObject promise_wrapper(context, CreateNativePromise(context));
  DCHECK(promise_wrapper);
  JS::RootedObject executor(context,
                            CreateExecutorArgument(context, promise_wrapper));
  DCHECK(executor);

  // Invoke the Promise constructor with the native executor function.
  const size_t kNumArguments = 1;
  JS::Value args[kNumArguments] = {OBJECT_TO_JSVAL(executor)};
  JS::RootedObject promise_object(context);
  promise_object = JS_New(context, constructor, kNumArguments, args);
  if (!promise_object) {
    DLOG(ERROR) << "Failed to create a new Promise.";
    return NULL;
  }
  // Maintain a handle to the promise object on the NativePromise.
  JS_SetReservedSlot(promise_wrapper, kPromiseObject,
                     OBJECT_TO_JSVAL(promise_object));

  return promise_wrapper;
}

JSObject* PromiseWrapper::GetPromise() const {
  JS::RootedObject promise(context_);
  JS::RootedObject promise_wrapper(context_, weak_promise_wrapper_.GetObject());
  if (promise_wrapper) {
    JS::RootedValue slot_value(
        context_, JS_GetReservedSlot(promise_wrapper, kPromiseObject));
    DCHECK(slot_value.isObject());
    promise = JSVAL_TO_OBJECT(slot_value);
  }
  return promise;
}

void PromiseWrapper::Resolve(JS::HandleValue value) const {
  JS::RootedObject promise_wrapper(context_, weak_promise_wrapper_.GetObject());
  if (promise_wrapper) {
    Settle(context_, value, promise_wrapper, kResolveFunction);
  }
}

void PromiseWrapper::Reject(JS::HandleValue value) const {
  JS::RootedObject promise_wrapper(context_, weak_promise_wrapper_.GetObject());
  if (promise_wrapper) {
    Settle(context_, value, promise_wrapper, kRejectFunction);
  }
}

PromiseWrapper::PromiseWrapper(JSContext* context,
                               JS::HandleObject promise_wrapper)
    : context_(context), weak_promise_wrapper_(context, promise_wrapper) {
  DCHECK_EQ(JS_GetClass(promise_wrapper), &native_promise_class);
}

}  // namespace mozjs
}  // namespace script
}  // namespace cobalt
