package pgtype

import (
	
	
	
)

type TextScanner interface {
	ScanText(v Text) error
}

type TextValuer interface {
	TextValue() (Text, error)
}

type Text struct {
	String string
	Valid  bool
}

func ( *Text) ( Text) error {
	* = 
	return nil
}

func ( Text) () (Text, error) {
	return , nil
}

// Scan implements the database/sql Scanner interface.
func ( *Text) ( any) error {
	if  == nil {
		* = Text{}
		return nil
	}

	switch src := .(type) {
	case string:
		* = Text{String: , Valid: true}
		return nil
	case []byte:
		* = Text{String: string(), Valid: true}
		return nil
	}

	return fmt.Errorf("cannot scan %T", )
}

// Value implements the database/sql/driver Valuer interface.
func ( Text) () (driver.Value, error) {
	if !.Valid {
		return nil, nil
	}
	return .String, nil
}

func ( Text) () ([]byte, error) {
	if !.Valid {
		return []byte("null"), nil
	}

	return json.Marshal(.String)
}

func ( *Text) ( []byte) error {
	var  *string
	 := json.Unmarshal(, &)
	if  != nil {
		return 
	}

	if  == nil {
		* = Text{}
	} else {
		* = Text{String: *, Valid: true}
	}

	return nil
}

type TextCodec struct{}

func (TextCodec) ( int16) bool {
	return  == TextFormatCode ||  == BinaryFormatCode
}

func (TextCodec) () int16 {
	return TextFormatCode
}

func (TextCodec) ( *Map,  uint32,  int16,  any) EncodePlan {
	switch  {
	case TextFormatCode, BinaryFormatCode:
		switch .(type) {
		case string:
			return encodePlanTextCodecString{}
		case []byte:
			return encodePlanTextCodecByteSlice{}
		case TextValuer:
			return encodePlanTextCodecTextValuer{}
		}
	}

	return nil
}

type encodePlanTextCodecString struct{}

func (encodePlanTextCodecString) ( any,  []byte) ( []byte,  error) {
	 := .(string)
	 = append(, ...)
	return , nil
}

type encodePlanTextCodecByteSlice struct{}

func (encodePlanTextCodecByteSlice) ( any,  []byte) ( []byte,  error) {
	 := .([]byte)
	 = append(, ...)
	return , nil
}

type encodePlanTextCodecStringer struct{}

func (encodePlanTextCodecStringer) ( any,  []byte) ( []byte,  error) {
	 := .(fmt.Stringer)
	 = append(, .String()...)
	return , nil
}

type encodePlanTextCodecTextValuer struct{}

func (encodePlanTextCodecTextValuer) ( any,  []byte) ( []byte,  error) {
	,  := .(TextValuer).TextValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = append(, .String...)
	return , nil
}

func (TextCodec) ( *Map,  uint32,  int16,  any) ScanPlan {

	switch  {
	case TextFormatCode, BinaryFormatCode:
		switch .(type) {
		case *string:
			return scanPlanTextAnyToString{}
		case *[]byte:
			return scanPlanAnyToNewByteSlice{}
		case BytesScanner:
			return scanPlanAnyToByteScanner{}
		case TextScanner:
			return scanPlanTextAnyToTextScanner{}
		}
	}

	return nil
}

func ( TextCodec) ( *Map,  uint32,  int16,  []byte) (driver.Value, error) {
	return .DecodeValue(, , , )
}

func ( TextCodec) ( *Map,  uint32,  int16,  []byte) (any, error) {
	if  == nil {
		return nil, nil
	}

	return string(), nil
}

type scanPlanTextAnyToString struct{}

func (scanPlanTextAnyToString) ( []byte,  any) error {
	if  == nil {
		return fmt.Errorf("cannot scan NULL into %T", )
	}

	 := ().(*string)
	* = string()

	return nil
}

type scanPlanAnyToNewByteSlice struct{}

func (scanPlanAnyToNewByteSlice) ( []byte,  any) error {
	 := ().(*[]byte)
	if  == nil {
		* = nil
	} else {
		* = make([]byte, len())
		copy(*, )
	}

	return nil
}

type scanPlanAnyToByteScanner struct{}

func (scanPlanAnyToByteScanner) ( []byte,  any) error {
	 := ().(BytesScanner)
	return .ScanBytes()
}

type scanPlanTextAnyToTextScanner struct{}

func (scanPlanTextAnyToTextScanner) ( []byte,  any) error {
	 := ().(TextScanner)

	if  == nil {
		return .ScanText(Text{})
	}

	return .ScanText(Text{String: string(), Valid: true})
}