{{/*
 Copyright 2021 The Dawn Authors

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

{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/idlgen/main.go to generate the
WebGPU.cpp source file.

See:
* https://github.com/ben-clayton/webidlparser/blob/main/ast/ast.go for the AST
  types used by this template
* tools/src/cmd/idlgen/main.go for additional structures and functions
  used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}

{{- Include "WebGPUCommon.tmpl" -}}

#include "src/dawn/node/interop/WebGPU.h"

#include <unordered_map>

#include "src/dawn/node/utils/Debug.h"

namespace wgpu {
namespace interop {

namespace {

{{template "Wrappers" $}}

}  // namespace

{{ range $ := .Declarations}}
{{-        if IsDictionary $}}{{template "Dictionary" $}}
{{-   else if IsInterface  $}}{{template "Interface"  $}}
{{-   else if IsEnum       $}}{{template "Enum"       $}}
{{-   end}}
{{- end}}


void Initialize(Napi::Env env) {
  auto* wrapper = Wrappers::Init(env);
  auto global = env.Global();
{{- range $ := .Declarations}}
{{-   if IsInterfaceOrNamespace $}}
{{-     if not (HasAnnotation $ "LegacyNoInterfaceObject")}}
  global.Set(Napi::String::New(env, "{{$.Name}}"), wrapper->{{$.Name}}_ctor.Value());
{{-     end}}
{{-   end}}
{{- end}}
}

}  // namespace interop
}  // namespace wgpu


{{- /*
--------------------------------------------------------------------------------
-- Wrappers emits the C++ 'Wrappers' class, which holds all the interface and
-- namespace interop wrapper classes.
--------------------------------------------------------------------------------
*/ -}}
{{- define "Wrappers"}}
// Wrappers holds all the Napi class constructors, and Napi::ObjectWrap type
// declarations, for each of the WebIDL interface and namespace types.
class Wrappers {
  Wrappers(Napi::Env env) {
{{-   range $ := .Declarations}}
{{-     if IsInterfaceOrNamespace $}}
    {{$.Name}}_ctor = Napi::Persistent(W{{$.Name}}::Class(env));
{{-     end}}
{{-   end}}
  }

  static Wrappers* instance;

public:
{{-   range $ := .Declarations}}
{{-     if IsInterfaceOrNamespace $}}{{template "Wrapper" $}}
{{-     end}}
{{-   end}}

  // Allocates and constructs the Wrappers instance
  static Wrappers* Init(Napi::Env env) {
    instance = new Wrappers(env);
    return instance;
  }

  // Destructs and frees the Wrappers instance
  static void Term(Napi::Env env) {
    delete instance;
    instance = nullptr;
  }

  static Wrappers* For(Napi::Env env) {
    // Currently Napi only actually supports a single Env, so there's no point
    // maintaining a map of Env to Wrapper. Note: This might not always be true.
    return instance;
  }

{{   range $ := .Declarations}}
{{-     if IsInterfaceOrNamespace $}}
  Napi::FunctionReference {{$.Name}}_ctor;
{{-     end}}
{{-   end}}
};

Wrappers* Wrappers::instance = nullptr;
{{- end}}


{{- /*
--------------------------------------------------------------------------------
-- Wrapper emits the C++ wrapper class for the given ast.Interface or
-- ast.Namespace.
-- This wrapper class inherits from Napi::ObjectWrap, which binds the lifetime
-- of the JavaScript object to the lifetime of the wrapper class instance.
-- If the wrapper is for an interface, the wrapper object holds a unique_ptr to
-- the interface implementation, and delegates all exposed method calls on to
-- the implementation.
-- See: https://github.com/nodejs/node-addon-api/blob/main/doc/object_wrap.md
--------------------------------------------------------------------------------
*/ -}}
{{- define "Wrapper"}}
  struct W{{$.Name}} : public Napi::ObjectWrap<W{{$.Name}}> {
{{-  $attributes := FlattenedAttributesOf $ }}
{{-  $constants  := FlattenedConstantsOf  $ }}
{{-  $methods    := FlattenedMethodsOf    $ }}
{{-  if IsInterface $}}
    std::unique_ptr<{{$.Name}}> impl;
{{-  end}}
    static Napi::Function Class(Napi::Env env) {
      return DefineClass(env, "{{$.Name}}", {
{{   if $s := SetlikeOf $}}
        InstanceMethod("has", &W{{$.Name}}::has),
        InstanceMethod("keys", &W{{$.Name}}::keys),
{{-  end}}
{{-  range $m := $methods}}
        InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}),
{{-  end}}
{{-  range $a := $attributes}}
{{-   if not (HasAnnotation $a "SameObject")}}
        InstanceAccessor("{{$a.Name}}", &W{{$.Name}}::get{{Title $a.Name}},
{{-    if $a.Readonly}} nullptr{{else}} &W{{$.Name}}::set{{Title $a.Name}}{{end -}}
        ),
{{-   end}}
{{-  end}}
{{-  range $c := $constants}}
        StaticValue("{{$c.Name}}", ToJS(env, {{$.Name}}::{{$c.Name}}), napi_default_jsproperty),
{{-  end}}
      });
    }

    W{{$.Name}}(const Napi::CallbackInfo& info) : ObjectWrap(info) {}

{{-  if $s := SetlikeOf $}}
    Napi::Value has(const Napi::CallbackInfo& info) {
      std::tuple<{{template "Type" $s.Elem}}> args;
      auto res = FromJS(info, args);
      if (res) {
          return ToJS(info.Env(), impl->has(info.Env(), std::get<0>(args)));
      }
      Napi::TypeError::New(info.Env(), res.error).ThrowAsJavaScriptException();
      return {};
    }
    Napi::Value keys(const Napi::CallbackInfo& info) {
      return ToJS(info.Env(), impl->keys(info.Env()));
    }
{{-  end}}
{{-  range $m := $methods}}
    Napi::Value {{$m.Name}}(const Napi::CallbackInfo& info) {
      std::string error;
{{-    range $overload_idx, $o := $m.Overloads}}
{{- $overloaded := gt (len $m.Overloads) 1}}
      { {{if $overloaded}}// Overload {{$overload_idx}}{{end}}
        std::tuple<
{{-        range $i, $p := $o.Parameters}}
{{-          if $i}}, {{end}}
{{-          if      $p.Init    }}DefaultedParameter<{{template "Type" $p.Type}}>
{{-          else if $p.Optional}}std::optional<{{template "Type" $p.Type}}>
{{-          else               }}{{template "Type" $p.Type}}
{{-          end}}
{{-        end}}> args;

{{-        range $i, $p := $o.Parameters}}
{{-          if $p.Init}}
        std::get<{{$i}} /* {{$p.Name}} */>(args).default_value = {{Eval "Literal" "Value" $p.Init "Type" $p.Type}};
{{-          end}}
{{-        end}}

        auto res = FromJS(info, args);
        if (res) {
          {{/* indent */}}INTEROP_LOG(
{{-        range $i, $p := $o.Parameters}}
{{-          if $i}}, ", {{$p.Name}}: "{{else}}"{{$p.Name}}: "{{end}}, std::get<{{$i}}>(args)
{{-        end}});
          {{/* indent */}}
{{-      if not (IsUndefinedType $o.Type) }}auto result = {{end -}}
          impl->{{$o.Name}}(info.Env(){{range $i, $_ := $o.Parameters}}, std::get<{{$i}}>(args){{end}});
          {{/* indent */ -}}
{{-      if   IsUndefinedType $o.Type}}return info.Env().Undefined();
{{-      else                        }}return ToJS(info.Env(), result);
{{-      end                         }}
        }
        error = {{if $overloaded}}"\noverload {{$overload_idx}} failed to match:\n" + {{end}}res.error;
      }
{{-    end}}
      Napi::TypeError::New(info.Env(), "no overload matched for {{$m.Name}}:\n" + error).ThrowAsJavaScriptException();
      return {};
    }
{{-  end}}

{{-  range $a := $attributes}}
{{-   if not (HasAnnotation $a "SameObject")}}
    Napi::Value get{{Title $a.Name}}(const Napi::CallbackInfo& info) {
      return ToJS(info.Env(), impl->get{{Title $a.Name}}(info.Env()));
    }
{{-   if not $a.Readonly}}
    void set{{Title $a.Name}}(const Napi::CallbackInfo& info, const Napi::Value& value) {
      {{template "Type" $a.Type}} v{};
      auto res = FromJS(info.Env(), value, v);
      if (res) {
        impl->set{{Title $a.Name}}(info.Env(), std::move(v));
      } else {
        res = res.Append("invalid value to {{$a.Name}}");
        Napi::TypeError::New(info.Env(), res.error).ThrowAsJavaScriptException();
      }
    }
{{-    end}}
{{-   end}}
{{-  end}}
  };
{{end}}


{{- /*
--------------------------------------------------------------------------------
-- Dictionary emits the C++ method implementations and associated functions of
-- the interop type that defines the given ast.Dictionary
--------------------------------------------------------------------------------
*/ -}}
{{- define "Dictionary"}}
Result Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}& out) {
  auto object = value.ToObject();
  Result res;
{{- template "DictionaryMembersFromJS" $}};
  return Success;
}

Napi::Value Converter<{{$.Name}}>::ToJS(Napi::Env env, {{$.Name}} value) {
  auto object = Napi::Object::New(env);
{{- template "DictionaryMembersToJS" $}}
  return object;
}

std::ostream& operator<<(std::ostream& o, const {{$.Name}}& dict) {
    o << "{{$.Name}} {";
{{-    range $i, $m := $.Members}}
    o << {{if $i}}", "{{else}}" "{{end}} << "{{$m.Name}}: ";
    utils::Write(o, dict.{{$m.Name}});
{{-    end          }}
    o << "}" << std::endl;
    return o;
}
{{ end}}


{{- /*
--------------------------------------------------------------------------------
-- DictionaryMembersFromJS emits the C++ logic to convert each of the
-- dictionary ast.Member fields from JavaScript to C++. Each call to ToJS() is
-- emitted as a separate statement, and requires a 'Result res' local to be
-- declared
--------------------------------------------------------------------------------
*/ -}}
{{- define "DictionaryMembersFromJS"}}
{{-    if $.Inherits}}{{template "DictionaryMembersFromJS" (Lookup $.Inherits)}}{{end}}
{{-    range $i, $m := $.Members}}
  {{/* indent */}}
{{-      if   $m.Init }}res = interop::FromJSOptional(env, object.Get("{{$m.Name}}"), out.{{$m.Name}});
{{-      else         }}res = interop::FromJS(env, object.Get("{{$m.Name}}"), out.{{$m.Name}});
{{-      end          }}
  if (!res) {
    return res.Append("while converting member '{{$m.Name}}'");
  }
{{-    end}}
{{- end}}


{{- /*
--------------------------------------------------------------------------------
-- DictionaryMembersToJS emits the C++ logic to convert each of the
-- dictionary ast.Member fields to JavaScript from C++. Each call to ToJS() is
-- emitted as a separate statement
--------------------------------------------------------------------------------
*/ -}}
{{- define "DictionaryMembersToJS"}}
{{-    if $.Inherits}}{{template "DictionaryMembersToJS" (Lookup $.Inherits)}}{{end}}
{{-    range $m := $.Members}}
  object.Set(Napi::String::New(env, "{{$m.Name}}"), interop::ToJS(env, value.{{$m.Name}}));
{{-    end}}
{{- end}}


{{- /*
--------------------------------------------------------------------------------
-- Interface emits the C++ method implementations that define the given
-- ast.Interface.
-- Note: Most of the actual binding logic lives in the interface wrapper class.
--------------------------------------------------------------------------------
*/ -}}
{{- define "Interface"}}
{{$.Name}}::{{$.Name}}() = default;

{{$.Name}}* {{$.Name}}::Unwrap(Napi::Object object) {
  auto* wrappers = Wrappers::For(object.Env());
  if (!object.InstanceOf(wrappers->{{$.Name}}_ctor.Value())) {
    return nullptr;
  }
  return Wrappers::W{{$.Name}}::Unwrap(object)->impl.get();
}

Interface<{{$.Name}}> {{$.Name}}::Bind(Napi::Env env, std::unique_ptr<{{$.Name}}>&& impl) {
  auto* wrappers = Wrappers::For(env);
  auto object = wrappers->{{$.Name}}_ctor.New({});
  auto* wrapper = Wrappers::W{{$.Name}}::Unwrap(object);
  wrapper->impl = std::move(impl);

{{- /*Add the [SameObject] members as read-only property on the JS object.*/ -}}
{{- range $a := AttributesOf $}}
{{-   if HasAnnotation $a "SameObject"}}
  object.DefineProperty(Napi::PropertyDescriptor::Value(
    "{{$a.Name}}", ToJS(env, wrapper->impl->get{{Title $a.Name}}(env))
  ));
{{-   end}}
{{- end}}

  return Interface<{{$.Name}}>(object);
}

{{$.Name}}::~{{$.Name}}() = default;
{{ end}}


{{- /*
--------------------------------------------------------------------------------
-- Enum emits the C++ associated functions of the interop type that defines the
-- given ast.Enum
--------------------------------------------------------------------------------
*/ -}}
{{- define "Enum"}}
bool Converter<{{$.Name}}>::FromString(std::string str, {{$.Name}}& out) {
{{-  range $e := $.Values}}
  if (str == {{$e.Value}}) {
    out = {{$.Name}}::{{EnumEntryName $e.Value}};
    return true;
  }
{{-  end}}
  return false;
}

const char* Converter<{{$.Name}}>::ToString({{$.Name}} value) {
  switch (value) {
{{-  range $e := $.Values}}
  case {{$.Name}}::{{EnumEntryName $e.Value}}:
    return {{$e.Value}};
{{-  end}}
  }
  return nullptr;
}

Result Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}& out) {
  std::string str = value.ToString();
  if (FromString(str, out)) {
    return Success;
  }
  return Error(str + " is not a valid enum value of {{$.Name}}");
}

Napi::Value Converter<{{$.Name}}>::ToJS(Napi::Env env, {{$.Name}} value) {
  switch (value) {
{{-  range $e := $.Values}}
  case {{$.Name}}::{{EnumEntryName $e.Value}}:
    return Napi::String::New(env, {{$e.Value}});
{{-  end}}
  }
  return env.Undefined();
}

std::ostream& operator<<(std::ostream& o, {{$.Name}} value) {
  if (auto* s = Converter<{{$.Name}}>::ToString(value)) {
    return o << s;
  }
  return o << "undefined<{{$.Name}}>";
}

{{end}}
