package schema

import (
	
	
	
	
	
	
	
	
	
	
	
)

var serializerMap = sync.Map{}

// RegisterSerializer register serializer
func ( string,  SerializerInterface) {
	serializerMap.Store(strings.ToLower(), )
}

// GetSerializer get serializer
func ( string) ( SerializerInterface,  bool) {
	,  := serializerMap.Load(strings.ToLower())
	if  {
		,  = .(SerializerInterface)
	}
	return , 
}

func init() {
	RegisterSerializer("json", JSONSerializer{})
	RegisterSerializer("unixtime", UnixSecondSerializer{})
	RegisterSerializer("gob", GobSerializer{})
}

// Serializer field value serializer
type serializer struct {
	Field           *Field
	Serializer      SerializerInterface
	SerializeValuer SerializerValuerInterface
	Destination     reflect.Value
	Context         context.Context
	value           interface{}
	fieldValue      interface{}
}

// Scan implements sql.Scanner interface
func ( *serializer) ( interface{}) error {
	.value = 
	return nil
}

// Value implements driver.Valuer interface
func ( serializer) () (driver.Value, error) {
	return .SerializeValuer.Value(.Context, .Field, .Destination, .fieldValue)
}

// SerializerInterface serializer interface
type SerializerInterface interface {
	Scan(ctx context.Context, field *Field, dst reflect.Value, dbValue interface{}) error
	SerializerValuerInterface
}

// SerializerValuerInterface serializer valuer interface
type SerializerValuerInterface interface {
	Value(ctx context.Context, field *Field, dst reflect.Value, fieldValue interface{}) (interface{}, error)
}

// JSONSerializer json serializer
type JSONSerializer struct{}

// Scan implements serializer interface
func (JSONSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) ( error) {
	 := reflect.New(.FieldType)

	if  != nil {
		var  []byte
		switch v := .(type) {
		case []byte:
			 = 
		case string:
			 = []byte()
		default:
			return fmt.Errorf("failed to unmarshal JSONB value: %#v", )
		}

		if len() > 0 {
			 = json.Unmarshal(, .Interface())
		}
	}

	.ReflectValueOf(, ).Set(.Elem())
	return
}

// Value implements serializer interface
func (JSONSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) (interface{}, error) {
	,  := json.Marshal()
	if string() == "null" {
		if .TagSettings["NOT NULL"] != "" {
			return "", nil
		}
		return nil, 
	}
	return string(), 
}

// UnixSecondSerializer json serializer
type UnixSecondSerializer struct{}

// Scan implements serializer interface
func (UnixSecondSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) ( error) {
	 := sql.NullTime{}
	if  = .Scan();  == nil && .Valid {
		 = .Set(, , .Time.Unix())
	}

	return
}

// Value implements serializer interface
func (UnixSecondSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) ( interface{},  error) {
	 := reflect.ValueOf()
	switch v := .(type) {
	case int64, int, uint, uint64, int32, uint32, int16, uint16:
		 = time.Unix(reflect.Indirect().Int(), 0)
	case *int64, *int, *uint, *uint64, *int32, *uint32, *int16, *uint16:
		if .IsZero() {
			return nil, nil
		}
		 = time.Unix(reflect.Indirect().Int(), 0)
	default:
		 = fmt.Errorf("invalid field type %#v for UnixSecondSerializer, only int, uint supported", )
	}
	return
}

// GobSerializer gob serializer
type GobSerializer struct{}

// Scan implements serializer interface
func (GobSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) ( error) {
	 := reflect.New(.FieldType)

	if  != nil {
		var  []byte
		switch v := .(type) {
		case []byte:
			 = 
		default:
			return fmt.Errorf("failed to unmarshal gob value: %#v", )
		}
		if len() > 0 {
			 := gob.NewDecoder(bytes.NewBuffer())
			 = .Decode(.Interface())
		}
	}
	.ReflectValueOf(, ).Set(.Elem())
	return
}

// Value implements serializer interface
func (GobSerializer) ( context.Context,  *Field,  reflect.Value,  interface{}) (interface{}, error) {
	 := new(bytes.Buffer)
	 := gob.NewEncoder().Encode()
	return .Bytes(), 
}