/*
 * 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-45/util/algorithm_helpers.h"

#include "base/logging.h"
#include "cobalt/script/mozjs-45/mozjs_exception_state.h"
#include "cobalt/script/mozjs-45/mozjs_global_environment.h"
#include "third_party/mozjs-45/js/src/jsapi.h"
#include "third_party/mozjs-45/js/src/jsarray.h"
#include "third_party/mozjs-45/js/src/jsiter.h"

namespace cobalt {
namespace script {
namespace mozjs {
namespace util {

namespace {
bool GetObjectProperty(JSContext* context, JS::HandleObject object,
                       const char* property_name,
                       JS::MutableHandleObject out_property) {
  DCHECK(context);
  DCHECK(object);
  DCHECK(property_name);

  JS::RootedValue property_value(context);
  if (!JS_GetProperty(context, object, property_name, &property_value)) {
    return false;
  }

  if (!property_value.isObjectOrNull()) {
    return false;
  }

  out_property.set(property_value.toObjectOrNull());
  return true;
}

bool GetSymbolIteratorId(JSContext* context, JS::MutableHandleId out_id) {
  DCHECK(context);

  MozjsGlobalEnvironment* env = MozjsGlobalEnvironment::GetFromContext(context);
  JS::RootedObject global(context, env->global_object_proxy());
  JS::RootedObject symbol(context);
  if (!GetObjectProperty(context, global, "Symbol", &symbol) || !symbol) {
    DLOG(INFO);
    return false;
  }

  JS::RootedValue iterator_symbol(context);
  if (!JS_GetProperty(context, symbol, "iterator", &iterator_symbol)) {
    DLOG(INFO);
    return false;
  }

  if (!iterator_symbol.isSymbol()) {
    DLOG(INFO);
    return false;
  }

  out_id.set(SYMBOL_TO_JSID(iterator_symbol.toSymbol()));
  return true;
}
}  // namespace

bool IsSameGcThing(JSContext* context, JS::HandleValue value1,
                   JS::HandleValue value2) {
  if (value1.isNullOrUndefined()) {
    return value2.isNullOrUndefined();
  }

  if (!value1.isGCThing() || !value2.isGCThing()) {
    return false;
  }

  return value1.toGCThing() == value2.toGCThing();
}

bool GetIterator(JSContext* context, JS::HandleObject object,
                 JS::MutableHandleObject out_iterator) {
  JS::RootedId id(context);
  if (!GetSymbolIteratorId(context, &id)) {
    DLOG(INFO);
    return false;
  }

  JS::RootedValue iterator_value(context);
  if (!Invoke0(context, object, id, &iterator_value)) {
    return false;
  }

  out_iterator.set(iterator_value.toObjectOrNull());
  return out_iterator;
}

bool IteratorNext(JSContext* context, JS::HandleObject iterator,
                  JS::MutableHandleObject out_iterator_result) {
  JS::RootedValue more(context);
  if (!js::IteratorMore(context, iterator, &more)) {
    MozjsExceptionState exception(context);
    exception.SetSimpleException(kNotIterableType);
    return false;
  }

  if (more.isMagic(JS_NO_ITER_VALUE)) {
    JS::RootedValue undefined(context, JS::UndefinedValue());
    out_iterator_result.set(
        js::CreateItrResultObject(context, undefined, true));
    return true;
  }

  out_iterator_result.set(js::CreateItrResultObject(context, more, false));
  return true;
}

bool IteratorComplete(JSContext* context, JS::HandleObject iterator_result) {
  JS::RootedValue done(context);
  if (!JS_GetProperty(context, iterator_result, "done", &done)) {
    return false;
  }

  return JS::ToBoolean(done);
}

bool IteratorValue(JSContext* context, JS::HandleObject iterator_result,
                   JS::MutableHandleValue out_result) {
  JS::RootedValue value(context);
  if (!JS_GetProperty(context, iterator_result, "value", &value)) {
    return false;
  }

  out_result.set(value);
  return true;
}

bool IteratorStep(JSContext* context, JS::HandleObject iterator,
                  JS::MutableHandleObject out_iterator_result) {
  JS::RootedObject result(context);
  if (!IteratorNext(context, iterator, &result)) {
    return false;
  }

  if (IteratorComplete(context, result)) {
    return false;
  }
  out_iterator_result.set(result);
  return true;
}

bool IteratorClose(JSContext* context, JS::HandleObject iterator) {
  return js::CloseIterator(context, iterator);
}

bool Call0(JSContext* context, JS::HandleFunction function,
           JS::HandleObject value, JS::MutableHandleValue out_result) {
  const size_t kNumArguments = 0;
  JS::AutoValueVector args(context);
  return JS::Call(context, value, function, args, out_result);
}

bool Invoke0(JSContext* context, JS::HandleObject value,
             const char* property_name, JS::MutableHandleValue out_result) {
  JS::RootedValue property(context);
  if (!JS_GetProperty(context, value, property_name, &property)) {
    return false;
  }

  if (!property.isObject() || !JS::IsCallable(property.toObjectOrNull())) {
    return false;
  }

  JS::RootedFunction function(context, JS_ValueToFunction(context, property));
  DCHECK(function);

  return util::Call0(context, function, value, out_result);
}

bool Invoke0(JSContext* context, JS::HandleObject value,
             JS::HandleId property_id, JS::MutableHandleValue out_result) {
  JS::RootedValue property(context);
  if (!JS_GetPropertyById(context, value, property_id, &property)) {
    return false;
  }

  if (!property.isObject() || !JS::IsCallable(property.toObjectOrNull())) {
    return false;
  }

  JS::RootedFunction function(context, JS_ValueToFunction(context, property));
  DCHECK(function);

  return util::Call0(context, function, value, out_result);
}

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