// Copyright 2016 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/wrapper_factory.h"

#include <utility>

#include "base/lazy_instance.h"
#include "cobalt/script/mozjs/mozjs_wrapper_handle.h"
#include "cobalt/script/mozjs/wrapper_private.h"
#include "third_party/mozjs/js/src/jsproxy.h"

namespace cobalt {
namespace script {
namespace mozjs {

void WrapperFactory::RegisterWrappableType(
    base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
    const PrototypeClassFunction& class_function) {
  std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib =
      wrappable_type_functions_.insert(std::make_pair(
          wrappable_type,
          WrappableTypeFunctions(create_function, class_function)));
  DCHECK(pib.second)
      << "RegisterWrappableType registered for type more than once.";
}

JSObject* WrapperFactory::GetWrapperProxy(
    const scoped_refptr<Wrappable>& wrappable) const {
  if (!wrappable) {
    return NULL;
  }

  JS::RootedObject wrapper_proxy(
      context_,
      MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get())));
  if (!wrapper_proxy) {
    scoped_ptr<Wrappable::WeakWrapperHandle> object_handle =
        CreateWrapper(wrappable);
    SetCachedWrapper(wrappable.get(), object_handle.Pass());
    wrapper_proxy =
        MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get()));
  }
  DCHECK(wrapper_proxy);
  DCHECK(js::IsProxy(wrapper_proxy));
  return wrapper_proxy;
}

bool WrapperFactory::HasWrapperProxy(
    const scoped_refptr<Wrappable>& wrappable) const {
  return wrappable &&
         !!MozjsWrapperHandle::GetObjectProxy(
             GetCachedWrapper(wrappable.get()));
}

bool WrapperFactory::IsWrapper(JS::HandleObject wrapper) const {
  // If the object doesn't have a wrapper private, it means that it is not a
  // platform object.
  return (JS_GetClass(wrapper)->flags & JSCLASS_HAS_PRIVATE) &&
         JS_GetPrivate(wrapper) != NULL;
}

scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
    const scoped_refptr<Wrappable>& wrappable) const {
  WrappableTypeFunctionsHashMap::const_iterator it =
      wrappable_type_functions_.find(wrappable->GetWrappableType());
  if (it == wrappable_type_functions_.end()) {
    NOTREACHED();
    return scoped_ptr<Wrappable::WeakWrapperHandle>();
  }
  JS::RootedObject new_proxy(
      context_, it->second.create_wrapper.Run(context_, wrappable));
  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromProxyObject(context_, new_proxy);
  DCHECK(wrapper_private);
  return make_scoped_ptr<Wrappable::WeakWrapperHandle>(
      new MozjsWrapperHandle(wrapper_private));
}

bool WrapperFactory::DoesObjectImplementInterface(JS::HandleObject object,
                                                  base::TypeId type_id) const {
  // If the object doesn't have a wrapper private which means it is not a
  // platform object, so the object doesn't implement the interface.
  if (!WrapperPrivate::HasWrapperPrivate(context_, object)) {
    return false;
  }

  WrappableTypeFunctionsHashMap::const_iterator it =
      wrappable_type_functions_.find(type_id);
  if (it == wrappable_type_functions_.end()) {
    NOTREACHED();
    return false;
  }
  const JSClass* proto_class = it->second.prototype_class.Run(context_);
  JS::RootedObject object_proto_object(context_);
  bool success =
      JS_GetPrototype(context_, object, object_proto_object.address());
  bool equality = false;
  while (!equality && success && object_proto_object) {
    // Get the class of the prototype.
    JSClass* object_proto_class = JS_GetClass(object_proto_object);
    equality = (object_proto_class == proto_class);
    // Get the prototype of the previous prototype.
    success = JS_GetPrototype(context_, object_proto_object,
                              object_proto_object.address());
  }
  return equality;
}
}  // namespace mozjs
}  // namespace script
}  // namespace cobalt
