package pgtype

import (
	
	
	
	
	
	

	
)

type LineScanner interface {
	ScanLine(v Line) error
}

type LineValuer interface {
	LineValue() (Line, error)
}

type Line struct {
	A, B, C float64
	Valid   bool
}

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

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

func ( *Line) ( any) error {
	return fmt.Errorf("cannot convert %v to Line", )
}

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

	switch src := .(type) {
	case string:
		return scanPlanTextAnyToLineScanner{}.Scan([]byte(), )
	}

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

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

	,  := LineCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
	if  != nil {
		return nil, 
	}
	return string(), 
}

type LineCodec struct{}

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

func (LineCodec) () int16 {
	return BinaryFormatCode
}

func (LineCodec) ( *Map,  uint32,  int16,  any) EncodePlan {
	if ,  := .(LineValuer); ! {
		return nil
	}

	switch  {
	case BinaryFormatCode:
		return encodePlanLineCodecBinary{}
	case TextFormatCode:
		return encodePlanLineCodecText{}
	}

	return nil
}

type encodePlanLineCodecBinary struct{}

func (encodePlanLineCodecBinary) ( any,  []byte) ( []byte,  error) {
	,  := .(LineValuer).LineValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = pgio.AppendUint64(, math.Float64bits(.A))
	 = pgio.AppendUint64(, math.Float64bits(.B))
	 = pgio.AppendUint64(, math.Float64bits(.C))
	return , nil
}

type encodePlanLineCodecText struct{}

func (encodePlanLineCodecText) ( any,  []byte) ( []byte,  error) {
	,  := .(LineValuer).LineValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = append(, fmt.Sprintf(`{%s,%s,%s}`,
		strconv.FormatFloat(.A, 'f', -1, 64),
		strconv.FormatFloat(.B, 'f', -1, 64),
		strconv.FormatFloat(.C, 'f', -1, 64),
	)...)
	return , nil
}

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

	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case LineScanner:
			return scanPlanBinaryLineToLineScanner{}
		}
	case TextFormatCode:
		switch .(type) {
		case LineScanner:
			return scanPlanTextAnyToLineScanner{}
		}
	}

	return nil
}

type scanPlanBinaryLineToLineScanner struct{}

func (scanPlanBinaryLineToLineScanner) ( []byte,  any) error {
	 := ().(LineScanner)

	if  == nil {
		return .ScanLine(Line{})
	}

	if len() != 24 {
		return fmt.Errorf("invalid length for line: %v", len())
	}

	 := binary.BigEndian.Uint64()
	 := binary.BigEndian.Uint64([8:])
	 := binary.BigEndian.Uint64([16:])

	return .ScanLine(Line{
		A:     math.Float64frombits(),
		B:     math.Float64frombits(),
		C:     math.Float64frombits(),
		Valid: true,
	})
}

type scanPlanTextAnyToLineScanner struct{}

func (scanPlanTextAnyToLineScanner) ( []byte,  any) error {
	 := ().(LineScanner)

	if  == nil {
		return .ScanLine(Line{})
	}

	if len() < 7 {
		return fmt.Errorf("invalid length for line: %v", len())
	}

	 := strings.SplitN(string([1:len()-1]), ",", 3)
	if len() < 3 {
		return fmt.Errorf("invalid format for line")
	}

	,  := strconv.ParseFloat([0], 64)
	if  != nil {
		return 
	}

	,  := strconv.ParseFloat([1], 64)
	if  != nil {
		return 
	}

	,  := strconv.ParseFloat([2], 64)
	if  != nil {
		return 
	}

	return .ScanLine(Line{A: , B: , C: , Valid: true})
}

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

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

	var  Line
	 := codecScan(, , , , , &)
	if  != nil {
		return nil, 
	}
	return , nil
}