/*
 * 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.
 */

#ifndef COBALT_SCRIPT_MOZJS_NATIVE_PROMISE_H_
#define COBALT_SCRIPT_MOZJS_NATIVE_PROMISE_H_

#include "cobalt/script/mozjs/conversion_helpers.h"
#include "cobalt/script/mozjs/mozjs_exception_state.h"
#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
#include "cobalt/script/mozjs/promise_wrapper.h"
#include "cobalt/script/mozjs/type_traits.h"
#include "cobalt/script/mozjs/weak_heap_object.h"
#include "cobalt/script/promise.h"
#include "third_party/mozjs/js/src/jsapi.h"

namespace cobalt {
namespace script {
namespace mozjs {

// Shared functionality for NativePromise<T>. Does not implement the Resolve
// function, since that needs to be specialized for Promise<T>.
template <typename T>
class NativePromiseBase : public Promise<T> {
 public:
  // ScriptObject boilerplate.
  typedef Promise<T> BaseType;
  JSObject* handle() const { return promise_resolver_->get().GetObject(); }
  const JS::Value& value() const { return promise_resolver_->get().GetValue(); }
  bool WasCollected() const { return promise_resolver_->get().WasCollected(); }

  // The Promise JS object (not the resolver).
  JSObject* promise() const { return promise_resolver_->GetPromise(); }

  void Reject() const OVERRIDE {
    JS::RootedObject promise_resolver(context_,
                                      promise_resolver_->get().GetObject());
    if (promise_resolver) {
      JSAutoRequest auto_request(context_);
      JSAutoCompartment auto_compartment(context_, promise_resolver);
      promise_resolver_->Reject(JS::UndefinedHandleValue);
    }
  }

  void Reject(SimpleExceptionType exception) const OVERRIDE {
    JS::RootedObject promise_resolver(context_,
                                      promise_resolver_->get().GetObject());
    if (promise_resolver) {
      JSAutoRequest auto_request(context_);
      JSAutoCompartment auto_compartment(context_, promise_resolver);
      JS::RootedValue error_result(
          context_, OBJECT_TO_JSVAL(MozjsExceptionState::CreateErrorObject(
                        context_, exception)));
      promise_resolver_->Reject(error_result);
    }
  }

  void Reject(const scoped_refptr<ScriptException>& result) const OVERRIDE {
    JS::RootedObject promise_resolver(context_,
                                      promise_resolver_->get().GetObject());
    if (promise_resolver) {
      JSAutoRequest auto_request(context_);
      JSAutoCompartment auto_compartment(context_, promise_resolver);
      JS::RootedValue converted_result(context_);
      ToJSValue(context_, result, &converted_result);
      promise_resolver_->Reject(converted_result);
    }
  }

 protected:
  NativePromiseBase(JSContext* context, JS::HandleObject resolver_object)
      : context_(context) {
    promise_resolver_.emplace(context, resolver_object);
  }

  NativePromiseBase(JSContext* context, JS::HandleValue resolver_value)
      : context_(context) {
    DCHECK(resolver_value.isObject());
    JS::RootedObject resolver_object(context, &resolver_value.toObject());
    promise_resolver_.emplace(context, resolver_object);
  }

  JSContext* context_;
  base::optional<PromiseWrapper> promise_resolver_;
};

// Implements the Resolve() function for T != void.
template <typename T>
class NativePromise : public NativePromiseBase<T> {
 public:
  NativePromise(JSContext* context, JS::HandleObject resolver_object)
      : NativePromiseBase<T>(context, resolver_object) {}

  NativePromise(JSContext* context, JS::HandleValue resolver_value)
      : NativePromiseBase<T>(context, resolver_value) {}

  void Resolve(const T& value) const OVERRIDE {
    JS::RootedObject promise_wrapper(
        this->context_, this->promise_resolver_->get().GetObject());
    if (promise_wrapper) {
      JSAutoRequest auto_request(this->context_);
      JSAutoCompartment auto_compartment(this->context_, promise_wrapper);
      JS::RootedValue converted_value(this->context_);
      ToJSValue(this->context_, value, &converted_value);
      this->promise_resolver_->Resolve(converted_value);
    }
  }
};

// Implements the Resolve() function for T == void.
template <>
class NativePromise<void> : public NativePromiseBase<void> {
 public:
  NativePromise(JSContext* context, JS::HandleObject resolver_object)
      : NativePromiseBase<void>(context, resolver_object) {}

  NativePromise(JSContext* context, JS::HandleValue resolver_value)
      : NativePromiseBase<void>(context, resolver_value) {}

  void Resolve() const OVERRIDE {
    JS::RootedObject promise_wrapper(context_,
                                     promise_resolver_->get().GetObject());
    if (promise_wrapper) {
      JSAutoRequest auto_request(context_);
      JSAutoCompartment auto_compartment(context_, promise_wrapper);
      promise_resolver_->Resolve(JS::UndefinedHandleValue);
    }
  }
};

template <typename T>
struct TypeTraits<NativePromise<T> > {
  typedef MozjsUserObjectHolder<NativePromise<T> > ConversionType;
  typedef const ScriptValue<Promise<T> >* ReturnType;
};

// Promise<T> -> JSValue
// Note that JSValue -> Promise<T> is not yet supported.
template <typename T>
inline void ToJSValue(JSContext* context,
                      const ScriptValue<Promise<T> >* promise_holder,
                      JS::MutableHandleValue out_value) {
  TRACK_MEMORY_SCOPE("Javascript");
  if (!promise_holder) {
    out_value.set(JS::NullValue());
    return;
  }
  const MozjsUserObjectHolder<NativePromise<T> >* user_object_holder =
      base::polymorphic_downcast<
          const MozjsUserObjectHolder<NativePromise<T> >*>(promise_holder);

  const NativePromise<T>* native_promise =
      base::polymorphic_downcast<const NativePromise<T>*>(
          user_object_holder->GetScriptValue());

  DCHECK(native_promise);
  out_value.setObjectOrNull(native_promise->promise());
}

// Destroys |promise_holder| as soon as the conversion is done.
// This is useful when a wrappable is not interested in retaining a reference
// to a promise, typically when a promise is resolved or rejected synchronously.
template <typename T>
inline void ToJSValue(JSContext* context,
                      scoped_ptr<ScriptValue<Promise<T> > > promise_holder,
                      JS::MutableHandleValue out_value) {
  ToJSValue(context, promise_holder.get(), out_value);
}

}  // namespace mozjs
}  // namespace script
}  // namespace cobalt
#endif  // COBALT_SCRIPT_MOZJS_NATIVE_PROMISE_H_
