{{ $view := . -}}
// Copyright © 2019 - 2020 Oscar Campos <oscar.campos@thepimpam.com>
// Copyright © 2017 - William Edwards
//
// 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.
package gdnative

// ==================================================================
// This file was autogenerated by PimPam GDNative-Go binding tools
// Please do not modify this file, any change will be lost
// ==================================================================

/*
#include "gdnative.gen.h"
{{ range $i, $header := $view.Headers -}}
	#include <{{ $header }}>
{{ end -}}
// Include all headers for now. TODO: Look up all the required
// headers we need to import based on the method arguments and return types.
#include <gdnative/aabb.h>
#include <gdnative/array.h>
#include <gdnative/basis.h>
#include <gdnative/color.h>
#include <gdnative/dictionary.h>
#include <gdnative/gdnative.h>
#include <gdnative/node_path.h>
#include <gdnative/plane.h>
#include <gdnative/pool_arrays.h>
#include <gdnative/quat.h>
#include <gdnative/rect2.h>
#include <gdnative/rid.h>
#include <gdnative/string.h>
#include <gdnative/string_name.h>
#include <gdnative/transform.h>
#include <gdnative/transform2d.h>
#include <gdnative/variant.h>
#include <gdnative/vector2.h>
#include <gdnative/vector3.h>
#include <gdnative_api_struct.gen.h>
*/
import "C"

{{/* Loop through and define all of the type definitions as Go structs -*/}}
{{ range $i, $typedef := $view.TypeDefinitions -}}
	{{/* Handle struct definitions */}}
	{{ if or (eq $typedef.Base "struct") (eq $typedef.Base "void") -}}
		// NewEmpty{{ $typedef.GoName }} will return a pointer to an empty
		// initialized {{ $typedef.GoName }}. This is primarily used in
		// conjunction with MethodBindPtrCall.
		func NewEmpty{{ $typedef.GoName }}() Pointer {
			var obj C.{{ $typedef.Name }}
			return Pointer{base: unsafe.Pointer(&obj)}
		}

		// NewPointerFrom{{ $typedef.GoName }} will return an unsafe pointer to the given
		// object. This is primarily used in conjunction with MethodBindPtrCall.
		func NewPointerFrom{{ $typedef.GoName }}(obj {{ $typedef.GoName }}) Pointer {
			return Pointer{base: unsafe.Pointer(obj.getBase())}
		}

		// New{{ $typedef.GoName }}FromPointer will return a {{ $typedef.GoName }} from the
		// given unsafe pointer. This is primarily used in conjunction with MethodBindPtrCall.
		func New{{ $typedef.GoName }}FromPointer(ptr Pointer) {{ $typedef.GoName }} {
			{{/* String structs should be handled differently -*/}}
			{{ if (eq $typedef.GoName "String") -}}
				base := (*C.godot_string)(ptr.getBase())
				utfStr := C.go_godot_string_utf8(GDNative.api, base)
				char := C.go_godot_char_string_get_data(GDNative.api, &utfStr)
				goStr := C.GoString(char)
				C.go_godot_char_string_destroy(GDNative.api, &utfStr)

				return String(goStr)
			{{ else -}}
				{{ if (eq $typedef.GoName "Object") -}}
					obj := (**C.{{ $typedef.Name }})(ptr.getBase())
					return {{ $typedef.GoName }}{base: *obj}
				{{ else -}}
					return {{ $typedef.GoName }}{base: (*C.{{ $typedef.Name }})(ptr.getBase())}
				{{ end -}}
			{{ end -}}
		}

		{{/* The String struct is a special case to be compatible with Go strings -*/}}
		{{ if (eq $typedef.GoName "String") -}}
			type {{ $typedef.GoName }} string

			func (s String) getBase() *C.godot_string {
				return stringAsGodotString(string(s))
			}
		{{/* Handle all other kinds of Godot structs -*/}}
		{{ else }}
			// {{ $typedef.GoName }} data structure wrapper
			type {{ $typedef.GoName }} struct {
				base *C.{{ $typedef.Name }}
				{{/* Handle struct properties */}}
				{{ range $j, $propdef := $typedef.Properties -}}
					{{ if ($view.IsValidProperty $propdef) -}}
						{{ if $propdef.IsPointer -}}
							{{ if (eq $typedef.GoName "Signal" ) -}}
								{{ $propdef.GoName }} []{{ $view.ToGoName $propdef.Base }}
							{{ end -}}
						{{ else -}}
							{{ $propdef.GoName }} {{ $view.ToGoName $propdef.Base }}
						{{ end -}}
					{{ end -}}
				{{ end -}}
			}

			// returns the wrapped C base data type for this type
			func (gdt {{ $typedef.GoName }}) getBase() *C.{{ $typedef.Name }} {
				return gdt.base
			}
		{{ end }}

		{{/* Handle struct methods */}}
		{{ range $j, $method := ($view.MethodsList $typedef) -}}
			{{/* Handle constructor methods -*/}}
				// {{ $view.ToGoMethodName $typedef $method }} {{ $method.Name }} {{ $method.Arguments }} {{ $method.ReturnType }}
			{{ if ($view.MethodIsConstructor $method) -}}
				func {{ $view.ToGoMethodName $typedef $method }}({{ range $k, $arg := $method.Arguments }}{{ if (ne $k 0) }}{{ $view.ToGoArgName (index $arg 1) }} {{ $view.ToGoArgType (index $arg 0) true }}, {{ end }}{{ end }}) {{ $typedef.GoName }} {
				var dest C.{{ $view.StripPointer (index (index $method.Arguments 0) 0) }} {{/* First argument is always the destination */}}
					{{ range $k, $arg := $method.Arguments -}}
						{{ if (ne $k 0 ) -}}
							{{ if $view.IsVoidPointerType (index $arg 0) -}}
								arg{{ $k }} := unsafe.Pointer({{ $view.ToGoArgName (index $arg 1) }}.getBase())
							{{ else -}}
								{{ if $view.IsDoublePointer (index $arg 0) -}}
									arg{{ $k }}Array := {{ $view.ToGoArgType (index $arg 0) false }}Array{array: {{ $view.ToGoArgName (index $arg 1) }}}
									arg{{ $k }} := arg{{ $k }}Array.getBase()
								{{ else -}}
									arg{{ $k }} := {{ $view.ToGoArgName (index $arg 1) }}.getBase()
								{{ end -}}
							{{ end -}}
						{{ end -}}
					{{ end -}}

					C.go_{{ $method.Name }}(GDNative.api, {{ range $k, $arg := $method.Arguments }}{{ if (eq $k 0) }}&dest, {{ else }}{{ $view.OutputCArg $arg }}arg{{ $k }}, {{ end }}{{ end }})
					return {{ $typedef.GoName }}{base: &dest}
				}
			{{/* Handle all other kinds of methods -*/}}
			{{ else -}}
				func (gdt *{{ $typedef.GoName }}) {{ $view.ToGoMethodName $typedef $method }}({{ range $k, $arg := $method.Arguments }}{{ if $view.NotSelfArg (index $arg 1) }}{{ $view.ToGoArgName (index $arg 1) }} {{ $view.ToGoArgType (index $arg 0) true }}, {{ end }}{{ end }})  {{ $view.ToGoReturnType $method.ReturnType }} {
					{{ range $k, $arg := $method.Arguments -}}
						{{ if $view.NotSelfArg (index $arg 1) -}}
							{{ if $view.IsVoidPointerType (index $arg 0) -}}
								arg{{ $k }} := unsafe.Pointer({{ $view.ToGoArgName (index $arg 1) }}.getBase())
							{{ else -}}
								{{ if $view.IsDoublePointer (index $arg 0) -}}
									arg{{ $k }}Array := {{ $view.ToGoArgType (index $arg 0) false }}Array{array: {{ $view.ToGoArgName (index $arg 1) }}}
									arg{{ $k }} := arg{{ $k }}Array.getBase()
								{{ else -}}
									arg{{ $k }} := {{ $view.ToGoArgName (index $arg 1) }}.getBase()
								{{ end -}}
							{{ end -}}
						{{ else -}}
							arg{{ $k }} := gdt.getBase()
						{{ end -}}
					{{ end }}
					{{ if $view.HasReturn $method.ReturnType }}
						ret := C.go_{{ $method.Name }}(GDNative.api, {{ range $k, $arg := $method.Arguments }}{{ $view.OutputCArg $arg }}arg{{ $k }}, {{ end }})

						{{ if $view.IsBasicType ($view.ToGoReturnType $method.ReturnType) -}}
							{{ if ($view.IsWcharT $method.ReturnType ) -}}
								{{ if ($view.HasPointerReturn $method.ReturnType) -}}
									return newWcharT(ret)
								{{ else }}
									return newWcharT(&ret)
								{{ end }}
							{{ else -}}
								return {{ $view.ToGoReturnType $method.ReturnType }}(ret)
							{{ end -}}
						{{ else -}}
							{{ if $view.HasPointerReturn $method.ReturnType }}
								{{ if (eq $method.ReturnType "godot_object *") -}}
									return {{ $view.ToGoReturnType $method.ReturnType }}{base: (*C.godot_object)(ret)}
								{{ else }}
									return {{ $view.ToGoReturnType $method.ReturnType }}{base: ret}
								{{ end }}
							{{ else }}
								{{ if (eq $method.ReturnType "godot_string") -}}
									utfStr := C.go_godot_string_utf8(GDNative.api, &ret)
									char := C.go_godot_char_string_get_data(GDNative.api, &utfStr)
									goStr := C.GoString(char)
									C.go_godot_char_string_destroy(GDNative.api, &utfStr)

									return String(goStr)
								{{ else -}}
									return {{ $view.ToGoReturnType $method.ReturnType }}{base: &ret}
								{{ end -}}
							{{ end }}
						{{ end -}}
					{{ else -}}
						C.go_{{ $method.Name }}(GDNative.api, {{ range $k, $arg := $method.Arguments }}arg{{ $k }}, {{ end }})
					{{ end -}}
				}
			{{ end }}
		{{ end }}

	{{ end }}

	{{/* Handle enum definitions */}}
	{{ if eq $typedef.Base "enum" }}
		// {{ $typedef.GoName }} is a Go wrapper for the C.{{ $typedef.Name }} enum type.
		type {{ $typedef.GoName }} int

		func (e {{ $typedef.GoName }}) getBase() C.{{ $typedef.Name }} {
			return C.{{ $typedef.Name }}(e)
		}

		const (
		{{ range $j, $propdef := $typedef.Properties -}}
			{{ if (ne $propdef.GoName "") -}}
				{{ $propdef.GoName }} {{ $typedef.GoName }} = {{ $j }} {{ if $propdef.Comment }}// {{ $propdef.Comment }}{{ end }}
			{{ end -}}
		{{ end -}}
		)

		// {{ $typedef.GoName }}LookupMap is a string-based lookup table of constants for {{ $typedef.GoName }}.
		var {{ $typedef.GoName }}LookupMap = map[string]{{ $typedef.GoName }}{
			{{ range $j, $propdef := $typedef.Properties -}}
				{{ if (ne $propdef.GoName "") -}}
					"{{ $propdef.GoName }}": {{ $propdef.GoName }},
				{{ end -}}
			{{ end -}}
		}

	{{ end }}

	{{/* Handle base type definitions */}}
	{{ if and ($typedef.SimpleType) (ne $typedef.Base "void") }}
		{{/* This segment handles godot_pool_*_access type definitions */}}
		{{ if ($view.IsGodotBaseType $typedef) }}
			// NewEmpty{{ $typedef.GoName }} will return a pointer to an empty
			// initialized {{ $typedef.GoName }}. This is primarily used in
			// conjunction with MethodBindPtrCall.
			func NewEmpty{{ $typedef.GoName }}() Pointer {
				var obj C.{{ $typedef.Name }}
				return Pointer{base: unsafe.Pointer(&obj)}
			}

			// NewPointerFrom{{ $typedef.GoName }} will return an unsafe pointer to the given
			// object. This is primarily used in conjunction with MethodBindPtrCall.
			func NewPointerFrom{{ $typedef.GoName }}(obj {{ $typedef.GoName }}) Pointer {
				return Pointer{base: unsafe.Pointer(obj.getBase())}
			}

			// New{{ $typedef.GoName }}FromPointer will return a {{ $typedef.GoName }} from the
			// given unsafe pointer. This is primarily used in conjunction with MethodBindPtrCall.
			func New{{ $typedef.GoName }}FromPointer(ptr Pointer) {{ $typedef.GoName }} {
				obj := (*C.{{ $typedef.Name }})(ptr.getBase())
				return {{ $typedef.GoName }}{base: obj}
			}

			type {{ $typedef.GoName }} struct {
				base *C.{{ $typedef.Name }}
				{{/* Handle struct properties */}}
				{{ range $j, $propdef := $typedef.Properties -}}
					{{ if ($view.IsValidProperty $propdef) -}}
						{{ $propdef.GoName }} {{ $view.ToGoName $propdef.Base }}
					{{ end -}}
				{{ end -}}
			}

			func (gdt {{ $typedef.GoName }}) getBase() *C.{{ $typedef.Name }} {
				return gdt.base
			}
		{{/* This segment handles base types like godot_bool */}}
		{{ else }}
			// NewEmpty{{ $typedef.GoName }} will return a pointer to an empty
			// initialized {{ $typedef.GoName }}. This is primarily used in
			// conjunction with MethodBindPtrCall.
			func NewEmpty{{ $typedef.GoName }}() Pointer {
				var obj C.{{ $typedef.Name }}
				return Pointer{base: unsafe.Pointer(&obj)}
			}

			// NewPointerFrom{{ $typedef.GoName }} will return an unsafe pointer to the given
			// object. This is primarily used in conjunction with MethodBindPtrCall.
			func NewPointerFrom{{ $typedef.GoName }}(obj {{ $typedef.GoName }}) Pointer {
				base := obj.getBase()
				return Pointer{base: unsafe.Pointer(&base)}
			}

			// New{{ $typedef.GoName }}FromPointer will return a {{ $typedef.GoName }} from the
			// given unsafe pointer. This is primarily used in conjunction with MethodBindPtrCall.
			func New{{ $typedef.GoName }}FromPointer(ptr Pointer) {{ $typedef.GoName }} {
				base := ptr.getBase()
				return {{ $typedef.GoName }}(*(*C.{{ $typedef.Name }})(base))
			}

			// {{ $typedef.GoName }} is a Go wrapper for the base C.{{ $typedef.Name }} type
			type {{ $typedef.GoName }} {{ $view.ToGoBaseType $typedef.Base }}

			func (t {{ $typedef.GoName }}) getBase() C.{{ $typedef.Name }} {
				return C.{{ $typedef.Name }}(t)
			}
		{{ end }}

	{{ end }}
{{ end }}
