package pgtype

import (
	
	
	
	
	
	

	
)

type PolygonScanner interface {
	ScanPolygon(v Polygon) error
}

type PolygonValuer interface {
	PolygonValue() (Polygon, error)
}

type Polygon struct {
	P     []Vec2
	Valid bool
}

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

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

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

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

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

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

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

	return string(), 
}

type PolygonCodec struct{}

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

func (PolygonCodec) () int16 {
	return BinaryFormatCode
}

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

	switch  {
	case BinaryFormatCode:
		return encodePlanPolygonCodecBinary{}
	case TextFormatCode:
		return encodePlanPolygonCodecText{}
	}

	return nil
}

type encodePlanPolygonCodecBinary struct{}

func (encodePlanPolygonCodecBinary) ( any,  []byte) ( []byte,  error) {
	,  := .(PolygonValuer).PolygonValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = pgio.AppendInt32(, int32(len(.P)))

	for ,  := range .P {
		 = pgio.AppendUint64(, math.Float64bits(.X))
		 = pgio.AppendUint64(, math.Float64bits(.Y))
	}

	return , nil
}

type encodePlanPolygonCodecText struct{}

func (encodePlanPolygonCodecText) ( any,  []byte) ( []byte,  error) {
	,  := .(PolygonValuer).PolygonValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = append(, '(')

	for ,  := range .P {
		if  > 0 {
			 = append(, ',')
		}
		 = append(, fmt.Sprintf(`(%s,%s)`,
			strconv.FormatFloat(.X, 'f', -1, 64),
			strconv.FormatFloat(.Y, 'f', -1, 64),
		)...)
	}

	 = append(, ')')

	return , nil
}

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

	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case PolygonScanner:
			return scanPlanBinaryPolygonToPolygonScanner{}
		}
	case TextFormatCode:
		switch .(type) {
		case PolygonScanner:
			return scanPlanTextAnyToPolygonScanner{}
		}
	}

	return nil
}

type scanPlanBinaryPolygonToPolygonScanner struct{}

func (scanPlanBinaryPolygonToPolygonScanner) ( []byte,  any) error {
	 := ().(PolygonScanner)

	if  == nil {
		return .ScanPolygon(Polygon{})
	}

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

	 := int(binary.BigEndian.Uint32())
	 := 4

	if 4+*16 != len() {
		return fmt.Errorf("invalid length for Polygon with %d points: %v", , len())
	}

	 := make([]Vec2, )
	for  := 0;  < len(); ++ {
		 := binary.BigEndian.Uint64([:])
		 += 8
		 := binary.BigEndian.Uint64([:])
		 += 8
		[] = Vec2{math.Float64frombits(), math.Float64frombits()}
	}

	return .ScanPolygon(Polygon{
		P:     ,
		Valid: true,
	})
}

type scanPlanTextAnyToPolygonScanner struct{}

func (scanPlanTextAnyToPolygonScanner) ( []byte,  any) error {
	 := ().(PolygonScanner)

	if  == nil {
		return .ScanPolygon(Polygon{})
	}

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

	 := make([]Vec2, 0)

	 := string([2:])

	for {
		 := strings.IndexByte(, ',')
		,  := strconv.ParseFloat([:], 64)
		if  != nil {
			return 
		}

		 = [+1:]
		 = strings.IndexByte(, ')')

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

		 = append(, Vec2{, })

		if +3 < len() {
			 = [+3:]
		} else {
			break
		}
	}

	return .ScanPolygon(Polygon{P: , Valid: true})
}

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

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

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