// {{classname}} - {{{description}}}{{^description}}struct for {{{classname}}}{{/description}}
type {{classname}} struct {
	{{#oneOf}}
	{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} *{{{.}}}
	{{/oneOf}}
}

{{#composedSchemas}}
    {{#oneOf}}
        // {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}} is is a convenience function that returns {{datatype}} wrapped in {{classname}}
        func {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}}(v *{{datatype}}) {{classname}} {
            return {{classname}}{
                {{#lambda.type-to-name}}{{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}{{/lambda.type-to-name}}: v,
            }
        }

        {{#defaultValue}}
            // {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}}OrDefault returns {{datatype}} wrapped in {{classname}} if not nil, or a default value if nil
            func {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}}OrDefault(v *{{datatype}}) {{classname}} {
                if v == nil {
                    return {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}}(utils.Ptr{{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}({{datatype}}({{defaultValue}})))
                }
                return {{#lambda.type-to-name}}{{datatype}}{{/lambda.type-to-name}}As{{classname}}(v)
            }
        {{/defaultValue}}
    {{/oneOf}}
{{/composedSchemas}}


// Validate validates this {{classname}}
func (o *{{classname}}) Validate() error{
{{#oneOf}}
    if o.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil {
    return nil
    }

{{/oneOf}}
return fmt.Errorf("No oneOf schemas were matched in {{classname}}")
}


// Unmarshal JSON data into one of the pointers in the struct
func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
	var err error
	{{#isNullable}}
	// this object is nullable so check if the payload is null or empty string
	if string(data) == "" || string(data) == "{}" {
		return nil
	}

	{{/isNullable}}
	{{#useOneOfDiscriminatorLookup}}
	{{#discriminator}}
	{{#mappedModels}}
	{{#-first}}
	// use discriminator value to speed up the lookup
	var jsonDict map[string]interface{}
	err = utils.NewStrictDecoder(data).Decode(&jsonDict)
	if err != nil {
		return fmt.Errorf("failed to unmarshal JSON into map for the discriminator lookup")
	}

	{{/-first}}
	// check if the discriminator value is '{{{mappingName}}}'
	if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" {
		// try to unmarshal JSON data into {{{modelName}}}
		err = json.Unmarshal(data, &dst.{{{modelName}}})
		if err == nil {
			return nil // data stored in dst.{{{modelName}}}, return on the first match
		} else {
			dst.{{{modelName}}} = nil
			return fmt.Errorf("failed to unmarshal {{classname}} as {{{modelName}}}: %s", err.Error())
		}
	}

	{{/mappedModels}}
	return nil
	{{/discriminator}}
	{{^discriminator}}
	match := 0
	{{#oneOf}}
	// try to unmarshal data into {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}
	err = json.Unmarshal(data, &dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}})
	if err == nil {
		json{{{.}}}, _ := json.Marshal(dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}})
		if string(json{{{.}}}) == "{}" { // empty struct
			dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
		} else {
			match++
		}
	} else {
		dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
	}

	{{/oneOf}}
	if match > 1 { // more than 1 match
		// reset to nil
		{{#oneOf}}
		dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
		{{/oneOf}}

		return fmt.Errorf("data matches more than one schema in oneOf({{classname}})")
	} else if match == 1 {
		return nil // exactly one match
	} else { // no match
		return fmt.Errorf("data failed to match schemas in oneOf({{classname}})")
	}
	{{/discriminator}}
	{{/useOneOfDiscriminatorLookup}}
	{{^useOneOfDiscriminatorLookup}}
	match := 0
	{{#oneOf}}
	// try to unmarshal data into {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}
	err = utils.NewStrictDecoder(data).Decode(&dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}})
	if err == nil {
		json{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}, _ := json.Marshal(dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}})
		if string(json{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}) == "{}" { // empty struct
			dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
		} else {
			match++
		}
	} else {
		dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
	}

	{{/oneOf}}
	if match > 1 { // more than 1 match
		// reset to nil
		{{#oneOf}}
		dst.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} = nil
		{{/oneOf}}

		return fmt.Errorf("data matches more than one schema in oneOf({{classname}})")
	} else if match == 1 {
		return nil // exactly one match
	} else { // no match
		return fmt.Errorf("data failed to match schemas in oneOf({{classname}})")
	}
	{{/useOneOfDiscriminatorLookup}}
}

// Marshal data from the first non-nil pointers in the struct to JSON
func (src {{classname}}) MarshalJSON() ([]byte, error) {
{{#oneOf}}
	if src.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil {
		return json.Marshal(&src.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}})
	}

{{/oneOf}}
	return nil, nil // no data in oneOf schemas
}

// Get the actual instance
func (obj *{{classname}}) GetActualInstance() (interface{}) {
	if obj == nil {
		return nil
	}
{{#oneOf}}
	if obj.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil {
		return obj.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}
	}

{{/oneOf}}
	// all schemas are nil
	return nil
}

{{>nullable_model}}
