package orm

import (
	
	

	

	
)

const (
	PrimaryKeyFlag = uint8(1) << iota
	ForeignKeyFlag
	NotNullFlag
	UseZeroFlag
	UniqueFlag
	ArrayFlag
)

type Field struct {
	Field reflect.StructField
	Type  reflect.Type
	Index []int

	GoName      string     // struct field name, e.g. Id
	SQLName     string     // SQL name, .e.g. id
	Column      types.Safe // escaped SQL name, e.g. "id"
	SQLType     string
	UserSQLType string
	Default     types.Safe
	OnDelete    string
	OnUpdate    string

	flags uint8

	append types.AppenderFunc
	scan   types.ScannerFunc

	isZero zerochecker.Func
}

func (,  []int) bool {
	if len() != len() {
		return false
	}
	for ,  := range  {
		if  != [] {
			return false
		}
	}
	return true
}

func ( *Field) () *Field {
	 := *
	.Index = .Index[:len(.Index):len(.Index)]
	return &
}

func ( *Field) ( uint8) {
	.flags |= 
}

func ( *Field) ( uint8) bool {
	return .flags& != 0
}

func ( *Field) ( reflect.Value) reflect.Value {
	return fieldByIndexAlloc(, .Index)
}

func ( *Field) ( reflect.Value) bool {
	return .hasZeroValue(, .Index)
}

func ( *Field) ( reflect.Value,  []int) bool {
	for ,  := range  {
		if .Kind() == reflect.Ptr {
			if .IsNil() {
				return true
			}
			 = .Elem()
		}
		 = .Field()
	}
	return .isZero()
}

func ( *Field) () bool {
	return !.hasFlag(UseZeroFlag)
}

func ( *Field) ( []byte,  reflect.Value,  int) []byte {
	,  := fieldByIndex(, .Index)
	if ! {
		return types.AppendNull(, )
	}

	if .NullZero() && .isZero() {
		return types.AppendNull(, )
	}
	if .append == nil {
		panic(fmt.Errorf("pg: AppendValue(unsupported %s)", .Type()))
	}
	return .append(, , )
}

func ( *Field) ( reflect.Value,  types.Reader,  int) error {
	if .scan == nil {
		return fmt.Errorf("pg: ScanValue(unsupported %s)", .Type)
	}

	var  reflect.Value
	if  == -1 {
		var  bool
		,  = fieldByIndex(, .Index)
		if ! {
			return nil
		}
	} else {
		 = fieldByIndexAlloc(, .Index)
	}

	return .scan(, , )
}

type Method struct {
	Index int

	flags int8

	appender func([]byte, reflect.Value, int) []byte
}

func ( *Method) ( int8) bool {
	return .flags& != 0
}

func ( *Method) ( reflect.Value) reflect.Value {
	return .Method(.Index).Call(nil)[0]
}

func ( *Method) ( []byte,  reflect.Value,  int) []byte {
	 := .Value()
	return .appender(, , )
}