// checks if the {{classname}} type satisfies the MappedNullable interface at compile time
var _ utils.MappedNullable = &{{classname}}{}

// {{classname}} {{{description}}}{{^description}}struct for {{{classname}}}{{/description}}
type {{classname}} struct {
{{#parent}}
{{^isMap}}
{{^isArray}}
	{{{parent}}}
{{/isArray}}
{{/isMap}}
{{#isArray}}
	Items {{{parent}}}
{{/isArray}}
{{/parent}}
{{#vars}}
{{^-first}}
{{/-first}}
{{#description}}
	// {{{.}}}
{{/description}}
{{#deprecated}}
	// Deprecated
{{/deprecated}}
	{{name}} {{^isNullable}}{{^isArray}}{{^isMap}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isMap}}{{/isArray}}{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
{{/vars}}
{{#isAdditionalPropertiesTrue}}
	AdditionalProperties map[string]interface{}
{{/isAdditionalPropertiesTrue}}
}

{{#isAdditionalPropertiesTrue}}
type _{{{classname}}} {{{classname}}}

{{/isAdditionalPropertiesTrue}}
// New{{classname}}With instantiates a new {{classname}} object
// This constructor will make sure properties required by API are set.
// For optional properties, it will set default values if they have been defined.
// The set of arguments will change when the set of required properties is changed
func New{{classname}}With({{#requiredVars}}{{nameInCamelCase}} {{dataType}}{{^-last}}, {{/-last}}{{/requiredVars}}) *{{classname}} {
	this := {{classname}}{}
{{#allVars}}
{{#required}}
	this.{{name}} = {{^isArray}}{{^isMap}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isMap}}{{/isArray}}{{nameInCamelCase}}
{{/required}}
{{^required}}
{{#defaultValue}}
{{^vendorExtensions.x-golang-is-container}}
{{^isReadOnly}}
{{#isNullable}}
	var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}}
	this.{{name}} = *New{{{dataType}}}(&{{nameInCamelCase}})
{{/isNullable}}
{{^isNullable}}
	var {{nameInCamelCase}} {{{dataType}}} = {{{.}}}
	this.{{name}} = {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}{{nameInCamelCase}}
{{/isNullable}}
{{/isReadOnly}}
{{/vendorExtensions.x-golang-is-container}}
{{/defaultValue}}
{{/required}}
{{/allVars}}
	return &this
}

// New{{classname}}WithDefault instantiates a new {{classname}} object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func New{{classname}}WithDefault() *{{classname}} {
	this := {{classname}}{}
{{#vars}}
{{#defaultValue}}
{{^vendorExtensions.x-golang-is-container}}
{{^isReadOnly}}
{{#isNullable}}
{{!we use datatypeWithEnum here, since it will represent the non-nullable name of the datatype, e.g. int64 for NullableInt64}}
	var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}}
	this.{{name}} = *New{{{dataType}}}(&{{nameInCamelCase}})
{{/isNullable}}
{{^isNullable}}
	var {{nameInCamelCase}} {{{dataType}}} = {{{.}}}
	this.{{name}} = &{{nameInCamelCase}}
{{/isNullable}}
{{/isReadOnly}}
{{/vendorExtensions.x-golang-is-container}}
{{/defaultValue}}
{{/vars}}
	return &this
}

// New{{classname}} is short for New{{classname}}WithDefault which instantiates a new {{classname}} object.
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func New{{classname}}() *{{classname}} {
    return New{{classname}}WithDefault()
}

// New{{classname}}Empty instantiates a new {{classname}} object with no properties set.
// This constructor will not assign any default values to properties.
func New{{classname}}Empty() *{{classname}} {
    this := {{classname}}{}
    return &this
}


// New{{classname}}s converts a list {{classname}} pointers to objects.
// This is helpful when the Set{{classname}} requires a list of objects
func New{{classname}}List(ps ...*{{classname}}) []{{classname}} {
	objs := []{{classname}}{}
	for _, p := range ps {
        objs = append(objs, *p)
    }
	return objs
}


// Validate validates this {{classname}}
// 1. If the required properties are not set, this will return an error
// 2. If properties are set, will check if nested required properties are set
func (o *{{classname}}) Validate() error{
{{#allVars}}
    {{#required}}
        if o.{{name}} == nil {
        return errors.New("{{name}} in {{classname}} must be set")
        }
    {{/required}}
{{/allVars}}
  // validate all nested properties
{{#allVars}}
    {{#isModel}}
        if o.{{name}} != nil {
            if err:=o.{{name}}.Validate(); err != nil {
                return err
            }
        }
    {{/isModel}}
{{/allVars}}
return nil
}

{{#vars}}
{{#required}}
// Get{{name}} returns the {{name}} field value
{{#isNullable}}
// If the value is explicit nil, the zero value for {{vendorExtensions.x-go-base-type}} will be returned
{{/isNullable}}
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} {
	if o == nil{{#isNullable}}{{^vendorExtensions.x-golang-is-container}} || o.{{name}}.Get() == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
		var ret {{vendorExtensions.x-go-base-type}}
		return ret
	}

{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
	return o.{{name}}
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	return *o.{{name}}.Get()
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
	return {{^isArray}}{{^isMap}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isMap}}{{/isArray}}o.{{name}}
{{/isNullable}}
}

// Get{{name}}Ok returns a tuple with the {{name}} field value
// and a boolean to check if the value has been set.
{{#isNullable}}
// NOTE: If the value is an explicit nil, `nil, true` will be returned
{{/isNullable}}
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Get{{name}}Ok() ({{^isMap}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isMap}}{{vendorExtensions.x-go-base-type}}, bool) {
	if o == nil{{#isNullable}}{{#vendorExtensions.x-golang-is-container}} || utils.IsNil(o.{{name}}){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
{{^isFreeFormObject}}
		return nil, false
	{{/isFreeFormObject}}
	{{#isFreeFormObject}}
		return {{vendorExtensions.x-go-base-type}}{}, false
	{{/isFreeFormObject}}
	}
{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
    {{! KubeVela: remove the de-pointer operator here }}
	return {{^isArray}}{{^isFreeFormObject}}{{/isFreeFormObject}}{{/isArray}}o.{{name}}, true
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	return o.{{name}}.Get(), o.{{name}}.IsSet()
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
    return {{^isMap}}{{^isArray}}{{^isFreeFormObject}}{{/isFreeFormObject}}{{/isArray}}{{/isMap}}o.{{name}}, true
{{/isNullable}}
}

// Set{{name}} sets field value
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) *{{classname}} {
{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
	o.{{name}} = v
    return o
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	o.{{name}}.Set(&v)
    return o
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
	o.{{name}} = {{^isMap}}{{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}{{/isMap}}v
    return o
{{/isNullable}}
}

{{/required}}
{{^required}}
// Get{{name}} returns the {{name}} field value if set, zero value otherwise{{#isNullable}} (both if not set or set to explicit null){{/isNullable}}.
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} {
	if o == nil{{^isNullable}} || utils.IsNil(o.{{name}}){{/isNullable}}{{#isNullable}}{{^vendorExtensions.x-golang-is-container}} || utils.IsNil(o.{{name}}.Get()){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
		var ret {{vendorExtensions.x-go-base-type}}
		return ret
	}
{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
	return o.{{name}}
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	return *o.{{name}}.Get()
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
	return {{^isMap}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isMap}}o.{{name}}
{{/isNullable}}
}

// Get{{name}}Ok returns a tuple with the {{name}} field value if set, nil otherwise
// and a boolean to check if the value has been set.
{{#isNullable}}
// NOTE: If the value is an explicit nil, `nil, true` will be returned
{{/isNullable}}
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Get{{name}}Ok() ({{^isMap}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isMap}}{{vendorExtensions.x-go-base-type}}, bool) {
	if o == nil{{^isNullable}} || utils.IsNil(o.{{name}}){{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}} || utils.IsNil(o.{{name}}){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
	{{^isFreeFormObject}}
		return nil, false
	{{/isFreeFormObject}}
	{{#isFreeFormObject}}
		return {{vendorExtensions.x-go-base-type}}{}, false
	{{/isFreeFormObject}}
	}
{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
	return {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}o.{{name}}, true
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	return o.{{name}}.Get(), o.{{name}}.IsSet()
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
	return o.{{name}}, true
{{/isNullable}}
}

// Has{{name}} returns a boolean if a field has been set.
func (o *{{classname}}) Has{{name}}() bool {
	if o != nil && {{^isNullable}}!utils.IsNil(o.{{name}}){{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}}utils.IsNil(o.{{name}}){{/vendorExtensions.x-golang-is-container}}{{^vendorExtensions.x-golang-is-container}}o.{{name}}.IsSet(){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
		return true
	}

	return false
}

// Set{{name}} gets a reference to the given {{dataType}} and assigns it to the {{nameInCamelCase}} field.
// {{Name}}: {{#description}} {{{.}}} {{/description}}
{{#deprecated}}
// Deprecated
{{/deprecated}}
func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) (*{{classname}}){
{{#isNullable}}
{{#vendorExtensions.x-golang-is-container}}
	o.{{name}} = v
{{/vendorExtensions.x-golang-is-container}}
{{^vendorExtensions.x-golang-is-container}}
	o.{{name}}.Set({{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}v)
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}
{{^isNullable}}
	o.{{name}} = {{^isMap}}{{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}{{/isMap}}v
{{/isNullable}}
return o
}
{{#isNullable}}
{{^vendorExtensions.x-golang-is-container}}
// Set{{name}}Nil sets the value for {{name}} to be an explicit nil
func (o *{{classname}}) Set{{name}}Nil() {
	o.{{name}}.Set(nil)
}

// Unset{{name}} ensures that no value is present for {{name}}, not even an explicit nil
func (o *{{classname}}) Unset{{name}}() {
	o.{{name}}.Unset()
}
{{/vendorExtensions.x-golang-is-container}}
{{/isNullable}}

{{/required}}
{{/vars}}
func (o {{classname}}) MarshalJSON() ([]byte, error) {
	toSerialize,err := o.ToMap()
	if err != nil {
		return []byte{}, err
	}
	return json.Marshal(toSerialize)
}

func (o {{classname}}) ToMap() (map[string]interface{}, error) {
	toSerialize := {{#isArray}}make([]interface{}, len(o.Items)){{/isArray}}{{^isArray}}map[string]interface{}{}{{/isArray}}
	{{#parent}}
	{{^isMap}}
	{{^isArray}}
	serialized{{parent}}, err{{parent}} := json.Marshal(o.{{parent}})
	if err{{parent}} != nil {
		return map[string]interface{}{}, err{{parent}}
	}
	err{{parent}} = json.Unmarshal([]byte(serialized{{parent}}), &toSerialize)
	if err{{parent}} != nil {
		return map[string]interface{}{}, err{{parent}}
	}
	{{/isArray}}
	{{/isMap}}
	{{#isArray}}
	for i, item := range o.Items {
		toSerialize[i] = item
	}
	{{/isArray}}
	{{/parent}}
	{{#vars}}
	{{! if argument is nullable, only serialize it if it is set}}
	{{#isNullable}}
	{{#vendorExtensions.x-golang-is-container}}
	{{! support for container fields is not ideal at this point because of lack of Nullable* types}}
	if o.{{name}} != nil {
		toSerialize["{{baseName}}"] = o.{{name}}
	}
	{{/vendorExtensions.x-golang-is-container}}
	{{^vendorExtensions.x-golang-is-container}}
	{{#required}}
	toSerialize["{{baseName}}"] = o.{{name}}.Get()
	{{/required}}
	{{^required}}
	if o.{{name}}.IsSet() {
		toSerialize["{{baseName}}"] = o.{{name}}.Get()
	}
	{{/required}}
	{{/vendorExtensions.x-golang-is-container}}
	{{/isNullable}}
	{{! if argument is not nullable, don't set it if it is nil}}
	{{^isNullable}}
	{{^isReadOnly}}
	{{#required}}
	toSerialize["{{baseName}}"] = o.{{name}}
	{{/required}}
	{{^required}}
	if !utils.IsNil(o.{{name}}) {
		toSerialize["{{baseName}}"] = o.{{name}}
	}
	{{/required}}
	{{/isReadOnly}}
	{{#isReadOnly}}
	// skip: {{baseName}} is readOnly
	{{/isReadOnly}}
	{{/isNullable}}
	{{/vars}}
	{{#isAdditionalPropertiesTrue}}

	for key, value := range o.AdditionalProperties {
		toSerialize[key] = value
	}

	{{/isAdditionalPropertiesTrue}}
	return toSerialize, nil
}

{{#isAdditionalPropertiesTrue}}
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
{{#parent}}
{{^isMap}}
	type {{classname}}WithoutEmbeddedStruct struct {
	{{#vars}}
	{{^-first}}
	{{/-first}}
	{{#description}}
		// {{{.}}}
	{{/description}}
	{{#deprecated}}
		// Deprecated
	{{/deprecated}}
		{{name}} {{^required}}{{^isNullable}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isNullable}}{{/required}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
	{{/vars}}
	}

	var{{{classname}}}WithoutEmbeddedStruct := {{{classname}}}WithoutEmbeddedStruct{}

	err = json.Unmarshal(bytes, &var{{{classname}}}WithoutEmbeddedStruct)
	if err == nil {
		var{{{classname}}} := _{{{classname}}}{}
		{{#vars}}
		var{{{classname}}}.{{{name}}} = var{{{classname}}}WithoutEmbeddedStruct.{{{name}}}
		{{/vars}}
		*o = {{{classname}}}(var{{{classname}}})
	} else {
		return err
	}

	var{{{classname}}} := _{{{classname}}}{}

	err = json.Unmarshal(bytes, &var{{{classname}}})
	if err == nil {
		o.{{{parent}}} = var{{{classname}}}.{{{parent}}}
	} else {
		return err
	}

	additionalProperties := make(map[string]interface{})

	if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
		{{#vars}}
		delete(additionalProperties, "{{{baseName}}}")
		{{/vars}}

		// remove fields from embedded structs
		reflect{{{parent}}} := reflect.ValueOf(o.{{{parent}}})
		for i := 0; i < reflect{{{parent}}}.Type().NumField(); i++ {
			t := reflect{{{parent}}}.Type().Field(i)

			if jsonTag := t.Tag.Get("json"); jsonTag != "" {
				fieldName := ""
				if commaIdx := strings.Index(jsonTag, ","); commaIdx > 0 {
					fieldName = jsonTag[:commaIdx]
				} else {
					fieldName = jsonTag
				}
				if fieldName != "AdditionalProperties" {
					delete(additionalProperties, fieldName)
				}
			}
		}

		o.AdditionalProperties = additionalProperties
	}

	return err
{{/isMap}}
{{#isMap}}
	var{{{classname}}} := _{{{classname}}}{}

	if err = json.Unmarshal(bytes, &var{{{classname}}}); err == nil {
		*o = {{{classname}}}(var{{{classname}}})
	}

	additionalProperties := make(map[string]interface{})

	if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
		{{#vars}}
		delete(additionalProperties, "{{{baseName}}}")
		{{/vars}}
		o.AdditionalProperties = additionalProperties
	}

	return err
{{/isMap}}
{{/parent}}
{{^parent}}
	var{{{classname}}} := _{{{classname}}}{}

	if err = json.Unmarshal(bytes, &var{{{classname}}}); err == nil {
		*o = {{{classname}}}(var{{{classname}}})
	}

	additionalProperties := make(map[string]interface{})

	if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
		{{#vars}}
		delete(additionalProperties, "{{{baseName}}}")
		{{/vars}}
		o.AdditionalProperties = additionalProperties
	}

	return err
{{/parent}}
}

{{/isAdditionalPropertiesTrue}}
{{#isArray}}
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
	return json.Unmarshal(bytes, &o.Items)
}

{{/isArray}}
{{>nullable_model}}
