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

// clang-format off

// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
// Auto-generated from template: bindings/v8c/templates/dictionary-conversion.cc.template


#include "v8c_gen_type_conversion.h"

#include "cobalt/bindings/testing/test_dictionary.h"

#include "cobalt/script/exception_state.h"
#include "v8/include/v8.h"
#include "cobalt/bindings/testing/arbitrary_interface.h"
#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"

using cobalt::bindings::testing::TestDictionary;
using cobalt::bindings::testing::ArbitraryInterface;
using cobalt::bindings::testing::V8cArbitraryInterface;

namespace cobalt {
namespace script {
namespace v8c {

void ToJSValue(
    v8::Isolate* isolate,
    const TestDictionary& in_dictionary,
    v8::Local<v8::Value>* out_value) {
  // Create a new object that will hold the dictionary values.
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  v8::Local<v8::Context> context = global_environment->context();
  v8::Local<v8::Object> dictionary_object = v8::Object::New(isolate);
  if (in_dictionary.has_boolean_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.boolean_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "booleanMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_short_clamp_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.short_clamp_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "shortClampMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_long_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.long_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "longMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_double_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.double_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "doubleMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_string_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.string_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "stringMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_interface_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.interface_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "interfaceMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_member_with_default()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.member_with_default(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "memberWithDefault",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_non_default_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.non_default_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "nonDefaultMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_any_member_with_default()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.any_member_with_default(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "anyMemberWithDefault",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  if (in_dictionary.has_any_member()) {
    v8::Local<v8::Value> member_value;
    ToJSValue(isolate, in_dictionary.any_member(), &member_value);
    v8::Maybe<bool> maybe_result = dictionary_object->DefineOwnProperty(
      context,
      v8::String::NewFromUtf8(
        isolate,
        "anyMember",
        v8::NewStringType::kInternalized
      ).ToLocalChecked(),
      member_value
    );
    DCHECK(maybe_result.FromJust());
  }
  *out_value = dictionary_object;
}

void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
                 int conversion_flags, ExceptionState* exception_state,
                 TestDictionary* out_dictionary) {
  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
  V8cExceptionState* v8c_exception_state = base::polymorphic_downcast<V8cExceptionState*>(exception_state);
  DCHECK(!v8c_exception_state->is_exception_set());


  // https://heycam.github.io/webidl/#es-dictionary
  if (value->IsNullOrUndefined()) {
    // The default constructor will assign appropriate values to dictionary
    // members with default values and leave the others unset.
    *out_dictionary = TestDictionary();
    return;
  }

  if (!value->IsObject()) {
    // 1. If Type(V) is not Undefined, Null or Object, then throw a TypeError.
    exception_state->SetSimpleException(kNotObjectType);
    return;
  }

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  v8::Local<v8::Context> context = global_environment->context();
  v8::MaybeLocal<v8::Object> maybe_dictionary_object = value->ToObject(context);
  v8::Local<v8::Object> dictionary_object;
  if (!maybe_dictionary_object.ToLocal(&dictionary_object)) {
    NOTREACHED();
    exception_state->SetSimpleException(kNotObjectType);
    return;
  }

  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "booleanMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      bool converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_boolean_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "shortClampMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      int16_t converted_value;
      FromJSValue(isolate,
                  member_value,
                  (kConversionFlagClamped),
                  exception_state,
                  &converted_value);
      out_dictionary->set_short_clamp_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "longMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      int32_t converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_long_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "doubleMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      double converted_value;
      FromJSValue(isolate,
                  member_value,
                  (kConversionFlagRestricted),
                  exception_state,
                  &converted_value);
      out_dictionary->set_double_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "stringMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      std::string converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_string_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "interfaceMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      scoped_refptr<ArbitraryInterface> converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_interface_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "memberWithDefault", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      int32_t converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_member_with_default(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "nonDefaultMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      int32_t converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_non_default_member(converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "anyMemberWithDefault", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      TypeTraits<::cobalt::script::ValueHandle >::ConversionType converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_any_member_with_default(&converted_value);
    }
  }
  {
    v8::MaybeLocal<v8::Value> maybe_member_value = dictionary_object->Get(
        context,
        v8::String::NewFromUtf8(isolate, "anyMember", v8::NewStringType::kInternalized).ToLocalChecked());
    v8::Local<v8::Value> member_value;
    if (!maybe_member_value.ToLocal(&member_value)) {
      exception_state->SetSimpleException(kSimpleError);
      return;
    }

    if (!member_value->IsUndefined()) {
      TypeTraits<::cobalt::script::ValueHandle >::ConversionType converted_value;
      FromJSValue(isolate,
                  member_value,
                  kNoConversionFlags,
                  exception_state,
                  &converted_value);
      out_dictionary->set_any_member(&converted_value);
    }
  }
}

}  // namespace v8c
}  // namespace script
}  // namespace cobalt

