// Copyright 2020 The Cobalt Authors. 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

