{% set ty_name = type.name | to_upper_camel_case -%}
{% set discriminator_field = type.discriminator_field | to_upper_camel_case -%}
{% set content_field = type.content_field | to_upper_camel_case -%}
{% set has_variant_with_no_schema_ref = type.variants | selectattr("schema_ref") | length != type.variants | length -%}
// Package svix this file is @generated DO NOT EDIT
package models

import (
	"encoding/json"
	"fmt"
)

{% if type.description is defined -%}
{{ type.description | to_doc_comment(style="go")}}
{% endif -%}
// When creating an {{ ty_name }}, use the appropriate {{ type.content_field }} structure based on the Type:
{% for schema_ref, vars in type.variants | groupby("schema_ref") -%}
	{% set use_type -%}
		{% if schema_ref is defined -%}
		Use {{ schema_ref | to_upper_camel_case }}
		{% else -%}
		No {{ type.content_field }} needed (nil or just ignore the {{ type.content_field }} field)
		{% endif -%}
	{% endset -%}
//   - {% for v in vars %}"{{ v.name }}"{% if not loop.last %},{% endif %}{% endfor %}: {{ use_type }}
{%- endfor -%}
type {{ ty_name }} struct {
	{% include "types/struct_fields.go.jinja" -%}
	{{ discriminator_field }} {{ ty_name }}{{ discriminator_field }} `json:"{{ type.discriminator_field }}"`
	{{ content_field }} {{ ty_name }}{{ content_field }} `json:"{{ type.content_field }}"`
}

type {{ ty_name }}{{ discriminator_field }} string

const (
	{% for v in type.variants -%}
	{{ ty_name }}{{ discriminator_field }}{{ v.name | to_upper_camel_case }} {{ ty_name }}{{ discriminator_field }} = "{{ v.name }}"
	{% endfor -%}
)


type {{ ty_name }}{{ content_field }} interface {
	is{{ ty_name }}{{ content_field }}()
}

{% for schema_ref in type.variants| map(attribute="schema_ref") | unique -%}
	{% if schema_ref is defined -%}
func ({{ schema_ref | to_upper_camel_case }}) is{{ ty_name }}{{ content_field }}(){}
	{% else -%}
func (emptyMap) is{{ ty_name }}{{ content_field }}(){}
	{% endif -%}
{% endfor %}

func (i *{{ ty_name }}) UnmarshalJSON(data []byte) error {
	type Alias {{ ty_name }}
	aux := struct {
		*Alias
		{{ content_field }} json.RawMessage `json:"{{ type.content_field }}"`
	}{Alias: (*Alias)(i)}

	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}

	var err error
	switch i.{{ discriminator_field }} {
	{% for schema_ref, vars in type.variants | groupby("schema_ref") -%}
		case {% for v in vars %}"{{ v.name }}"{%if not loop.last%},{% endif %}{% endfor %}:
			{% if schema_ref is defined -%}
			var c {{ schema_ref | to_upper_camel_case }}
			err = json.Unmarshal(aux.{{ content_field }}, &c)
			i.{{ content_field }} = c
			{% endif -%}
	{% endfor -%}
	default:
		// should be unreachable
		return fmt.Errorf("unexpected type %s", i.{{ discriminator_field }})
	}
	return err
}

{% if has_variant_with_no_schema_ref -%}
var {{ ty_name }}{{ discriminator_field }}WithNo{{ content_field }} = map[string]bool{
	{% for v in type.variants -%}
		{% if v.schema_ref is not defined -%}
	"{{ v.name }}": true,
		{% endif -%}
	{% endfor -%}
}
{% endif -%}

func (i {{ ty_name }}) MarshalJSON() ([]byte, error) {
	type Alias {{ ty_name }}
	{% if has_variant_with_no_schema_ref -%}
	if _, found := {{ ty_name }}{{ discriminator_field }}WithNo{{ content_field }}[string(i.{{ discriminator_field }})]; found {
 		i.{{ content_field }} = emptyMap{}
	}
	{% endif -%}
	return json.Marshal(&struct {Alias}{Alias: (Alias)(i)})
}

var {{ ty_name }}{{ discriminator_field }}FromString = map[string]{{ ty_name }}{{ discriminator_field }}{
	{% for v in type.variants -%}
	"{{ v.name }}" : {{ ty_name }}{{ discriminator_field }}{{ v.name | to_upper_camel_case }},
	{% endfor -%}
}
