{{ define "numeric" }}
// Copyright 2019-present Facebook Inc. All rights reserved.
// This source code is licensed under the Apache 2.0 license found
// in the LICENSE file in the root directory of this source tree.

// Code generated by internal/numeric.tmpl, DO NOT EDIT.

package field

import (
	"errors"
	"reflect"
	"strings"

	"entgo.io/ent/schema"
)

//go:generate go run internal/gen.go

{{ range $t := $.Ints }}
	{{ $title := title $t.String }}
	// {{ $title }} returns a new Field with type {{ $t }}.
	func {{ $title }}(name string) *{{ $t }}Builder { return &{{ $t }}Builder{&Descriptor{
			Name: name,
			Info: &TypeInfo{Type: Type{{ $title }} },
		}}
	}
{{ end }}

// Float returns a new Field with type float64.
func Float(name string) *float64Builder { return &float64Builder{&Descriptor{
		Name: name,
		Info: &TypeInfo{Type: TypeFloat64},
	}}
}

// Float32 returns a new Field with type float32.
func Float32(name string) *float32Builder { return &float32Builder{&Descriptor{
		Name: name,
		Info: &TypeInfo{Type: TypeFloat32},
	}}
}

{{ range $t := $.Ints }}
{{ $builder := printf "%sBuilder" $t }}

// {{ $builder }} is the builder for {{ $t }} field.
type {{ $builder }} struct {
	desc *Descriptor
}

// Unique makes the field unique within all vertices of this type.
func (b *{{ $builder }}) Unique() *{{ $builder }} {
	b.desc.Unique = true
	return b
}

// Range adds a range validator for this field where the given value needs to be in the range of [i, j].
func (b *{{ $builder }}) Range(i, j {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v {{ $t }}) error {
		if v < i || v > j {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Min adds a minimum value validator for this field. Operation fails if the validator fails.
func (b *{{ $builder }}) Min(i {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v {{ $t }}) error {
		if v < i {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Max adds a maximum value validator for this field. Operation fails if the validator fails.
func (b *{{ $builder }}) Max(i {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v {{ $t }}) error {
		if v > i {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Positive adds a minimum value validator with the value of 1. Operation fails if the validator fails.
func (b *{{ $builder }}) Positive() *{{ $builder }} {
	return b.Min(1)
}

{{ if hasPrefix $t.String "uint" | not }}
	// Negative adds a maximum value validator with the value of -1. Operation fails if the validator fails.
	func (b *{{ $builder }}) Negative() *{{ $builder }} {
		return b.Max(-1)
	}

	// NonNegative adds a minimum value validator with the value of 0. Operation fails if the validator fails.
	func (b *{{ $builder }}) NonNegative() *{{ $builder }} {
		return b.Min(0)
	}
{{ end }}

// Default sets the default value of the field.
func (b *{{ $builder }}) Default(i {{ $t }}) *{{ $builder }} {
	b.desc.Default = i
	return b
}

// DefaultFunc sets the function that is applied to set the default value
// of the field on creation.
func (b *{{ $builder }}) DefaultFunc(fn any) *{{ $builder }} {
	b.desc.Default = fn
	return b
}

// UpdateDefault sets the function that is applied to set default value
// of the field on update. For example:
//
//	field.{{ title $t.String }}("{{$t.String}}").
//		Default(0).
//		UpdateDefault(GenNumber),
//
func (b *{{ $builder }}) UpdateDefault(fn any) *{{ $builder }} {
    b.desc.UpdateDefault = fn
    return b
}

// Nillable indicates that this field is a nillable.
// Unlike "Optional" only fields, "Nillable" fields are pointers in the generated struct.
func (b *{{ $builder }}) Nillable() *{{ $builder }} {
	b.desc.Nillable = true
	return b
}

// Comment sets the comment of the field.
func (b *{{ $builder }}) Comment(c string) *{{ $builder }} {
	b.desc.Comment = c
	return b
}

// Optional indicates that this field is optional on create.
// Unlike edges, fields are required by default.
func (b *{{ $builder }}) Optional() *{{ $builder }} {
	b.desc.Optional = true
	return b
}

// Immutable indicates that this field cannot be updated.
func (b *{{ $builder }}) Immutable() *{{ $builder }} {
	b.desc.Immutable = true
	return b
}

// StructTag sets the struct tag of the field.
func (b *{{ $builder }}) StructTag(s string) *{{ $builder }} {
	b.desc.Tag = s
	return b
}

// Validate adds a validator for this field. Operation fails if the validation fails.
func (b *{{ $builder }}) Validate(fn func({{ $t }}) error) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, fn)
	return b
}

// StorageKey sets the storage key of the field.
// In SQL dialects is the column name and Gremlin is the property.
func (b *{{ $builder }}) StorageKey(key string) *{{ $builder }} {
	b.desc.StorageKey = key
	return b
}

// SchemaType overrides the default database type with a custom
// schema type (per dialect) for {{ $t.String }}.
//
//	field.{{ title $t.String }}("oid").
//		SchemaType(map[string]string{
//			dialect.Postgres: "CustomType",
//		})
//
func (b *{{ $builder }}) SchemaType(types map[string]string) *{{ $builder }} {
	b.desc.SchemaType = types
	return b
}

{{ $tt := title $t.String }}
// GoType overrides the default Go type with a custom one.
// If the provided type implements the Validator interface
// and no validators have been set, the type validator will
// be used.
//
//	field.{{ $tt }}("{{ $t }}").
//		GoType(pkg.{{ $tt }}(0))
//
// Note that, the custom Go type `T` needs to implement the
// `Add(T) T` method in order to support the `Add<F>` operation
// in mutations. For example:
//
//	func(t1 T) Add(t2 T) T {
//		return add(t1, t2)
//	}
//
func (b *{{ $builder }}) GoType(typ any) *{{ $builder }} {
	b.desc.goType(typ)
	return b
}

// ValueScanner provides an external value scanner for the given GoType.
// Using this option allow users to use field types that do not implement
// the sql.Scanner and driver.Valuer interfaces.
func (b *{{ $builder }}) ValueScanner(vs any) *{{ $builder }} {
	b.desc.ValueScanner = vs
	return b
}

// Annotations adds a list of annotations to the field object to be used by
// codegen extensions.
//
//	field.{{ $tt }}("{{ $t }}").
//		Annotations(entgql.OrderField("{{ $t.String | toUpper }}"))
//
func (b *{{ $builder }}) Annotations(annotations ...schema.Annotation) *{{ $builder }} {
	b.desc.Annotations = append(b.desc.Annotations, annotations...)
	return b
}

// Deprecated marks the field as deprecated. Deprecated fields are not
// selected by default in queries, and their struct fields are annotated
// with `deprecated` in the generated code.
func (b *{{ $builder }}) Deprecated(reason ...string) *{{ $builder }} {
	b.desc.Deprecated = true
	if len(reason) > 0 {
		b.desc.DeprecatedReason = strings.Join(reason, " ")
	}
	return b
}

// Descriptor implements the ent.Field interface by returning its descriptor.
func (b *{{ $builder }}) Descriptor() *Descriptor {
	if b.desc.Default != nil || b.desc.UpdateDefault != nil {
		b.desc.checkDefaultFunc({{ $t }}Type)
	}
	b.desc.checkGoType({{ $t }}Type)
	return b.desc
}

{{ end }}

var (
	{{- range $t := $.Ints }}
		{{ $t }}Type = reflect.TypeOf({{ $t }}(0))
	{{- end }}
)

{{ range $t := $.Floats }}
{{ $builder := printf "%sBuilder" $t }}

// {{ $builder }} is the builder for float fields.
type {{ $builder }} struct {
	desc *Descriptor
}

// Unique makes the field unique within all vertices of this type.
func (b *{{ $builder }}) Unique() *{{ $builder }} {
	b.desc.Unique = true
	return b
}

// Range adds a range validator for this field where the given value needs to be in the range of [i, j].
func (b *{{ $builder }}) Range(i, j {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v  {{ $t }}) error {
		if v < i || v > j {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Min adds a minimum value validator for this field. Operation fails if the validator fails.
func (b *{{ $builder }}) Min(i  {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v  {{ $t }}) error {
		if v < i {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Max adds a maximum value validator for this field. Operation fails if the validator fails.
func (b *{{ $builder }}) Max(i {{ $t }}) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, func(v {{ $t }}) error {
		if v > i {
			return errors.New("value out of range")
		}
		return nil
	})
	return b
}

// Positive adds a minimum value validator with the value of 0.000001. Operation fails if the validator fails.
func (b *{{ $builder }}) Positive() *{{ $builder }} {
	return b.Min(1e-06)
}

// Negative adds a maximum value validator with the value of -0.000001. Operation fails if the validator fails.
func (b *{{ $builder }}) Negative() *{{ $builder }} {
	return b.Max(-1e-06)
}

// Default sets the default value of the field.
func (b *{{ $builder }}) Default(i {{ $t }}) *{{ $builder }} {
	b.desc.Default = i
	return b
}

// DefaultFunc sets the function that is applied to set the default value
// of the field on creation.
func (b *{{ $builder }}) DefaultFunc(fn any) *{{ $builder }} {
	b.desc.Default = fn
	return b
}

// UpdateDefault sets the function that is applied to set default value
// of the field on update. For example:
//
//	field.{{ title $t.String }}("{{$t.String}}").
//		Default(0).
//		UpdateDefault(GenNumber),
//
func (b *{{ $builder }}) UpdateDefault(fn any) *{{ $builder }} {
	b.desc.UpdateDefault = fn
	return b
}

// Nillable indicates that this field is a nillable.
// Unlike "Optional" only fields, "Nillable" fields are pointers in the generated struct.
func (b *{{ $builder }}) Nillable() *{{ $builder }} {
	b.desc.Nillable = true
	return b
}

// Comment sets the comment of the field.
func (b *{{ $builder }}) Comment(c string) *{{ $builder }} {
	b.desc.Comment = c
	return b
}

// Optional indicates that this field is optional on create.
// Unlike edges, fields are required by default.
func (b *{{ $builder }}) Optional() *{{ $builder }} {
	b.desc.Optional = true
	return b
}

// Immutable indicates that this field cannot be updated.
func (b *{{ $builder }}) Immutable() *{{ $builder }} {
	b.desc.Immutable = true
	return b
}

// StructTag sets the struct tag of the field.
func (b *{{ $builder }}) StructTag(s string) *{{ $builder }} {
	b.desc.Tag = s
	return b
}

// Validate adds a validator for this field. Operation fails if the validation fails.
func (b *{{ $builder }}) Validate(fn func({{ $t }}) error) *{{ $builder }} {
	b.desc.Validators = append(b.desc.Validators, fn)
	return b
}


// StorageKey sets the storage key of the field.
// In SQL dialects is the column name and Gremlin is the property.
func (b *{{ $builder }}) StorageKey(key string) *{{ $builder }} {
	b.desc.StorageKey = key
	return b
}

// SchemaType overrides the default database type with a custom
// schema type (per dialect) for {{ $t.String }}.
//
//	field.{{ title $t.String }}("amount").
//		SchemaType(map[string]string{
//			dialect.MySQL:		"decimal(5, 2)",
//			dialect.Postgres: 	"numeric(5, 2)",
//		})
//
func (b *{{ $builder }}) SchemaType(types map[string]string) *{{ $builder }} {
	b.desc.SchemaType = types
	return b
}

{{ $tt := title $t.String }}
// GoType overrides the default Go type with a custom one.
// If the provided type implements the Validator interface
// and no validators have been set, the type validator will
// be used.
//
//	field.{{ $tt }}("{{ $t }}").
//		GoType(pkg.{{ $tt }}(0))
//
// Note that, the custom Go type `T` needs to implement the
// `Add(T) T` method in order to support the `Add<F>` operation
// in mutations. For example:
//
//	func(t1 T) Add(t2 T) T {
//		return add(t1, t2)
//	}
//
func (b *{{ $builder }}) GoType(typ any) *{{ $builder }} {
	b.desc.goType(typ)
	return b
}

// ValueScanner provides an external value scanner for the given GoType.
// Using this option allow users to use field types that do not implement
// the sql.Scanner and driver.Valuer interfaces.
func (b *{{ $builder }}) ValueScanner(vs any) *{{ $builder }} {
	b.desc.ValueScanner = vs
	return b
}

// Annotations adds a list of annotations to the field object to be used by
// codegen extensions.
//
//	field.{{ $tt }}("{{ $t }}").
//		Annotations(entgql.OrderField("{{ $t.String | toUpper }}"))
//
func (b *{{ $builder }}) Annotations(annotations ...schema.Annotation) *{{ $builder }} {
	b.desc.Annotations = append(b.desc.Annotations, annotations...)
	return b
}

// Deprecated marks the field as deprecated. Deprecated fields are not
// selected by default in queries, and their struct fields are annotated
// with `deprecated` in the generated code.
func (b *{{ $builder }}) Deprecated(reason ...string) *{{ $builder }} {
	b.desc.Deprecated = true
	if len(reason) > 0 {
		b.desc.DeprecatedReason = strings.Join(reason, " ")
	}
	return b
}

// Descriptor implements the ent.Field interface by returning its descriptor.
func (b *{{ $builder }}) Descriptor() *Descriptor {
	if b.desc.Default != nil || b.desc.UpdateDefault != nil {
		b.desc.checkDefaultFunc({{ $t }}Type)
	}
	b.desc.checkGoType({{ $t }}Type)
	return b.desc
}
{{ end }}

var (
{{- range $t := $.Floats }}
    {{ $t }}Type = reflect.TypeOf({{ $t }}(0))
{{- end }}
)

{{ end }}
