{{/*
 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 src/dawn/node/tools/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
* src/dawn/node/tools/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}}> {
{{-  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 := MethodsOf $}}
        InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}),
{{-  end}}
{{-  range $a := AttributesOf $}}
{{-   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 := ConstantsOf $}}
        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::Error::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 := MethodsOf $}}
    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::Error::New(info.Env(), "no overload matched for {{$m.Name}}:\n" + error).ThrowAsJavaScriptException();
      return {};
    }
{{-  end}}

{{-  range $a := AttributesOf $}}
{{-   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::Error::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}}
