package pgtype

import (
	
	
	
	
	
)

type JSONCodec struct {
	Marshal   func(v any) ([]byte, error)
	Unmarshal func(data []byte, v any) error
}

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

func (*JSONCodec) () int16 {
	return TextFormatCode
}

func ( *JSONCodec) ( *Map,  uint32,  int16,  any) EncodePlan {
	switch .(type) {
	case string:
		return encodePlanJSONCodecEitherFormatString{}
	case []byte:
		return encodePlanJSONCodecEitherFormatByteSlice{}

	// Handle json.RawMessage specifically because if it is run through json.Marshal it may be mutated.
	// e.g. `{"foo": "bar"}` -> `{"foo":"bar"}`.
	case json.RawMessage:
		return encodePlanJSONCodecEitherFormatJSONRawMessage{}

	// Cannot rely on driver.Valuer being handled later because anything can be marshalled.
	//
	// https://github.com/jackc/pgx/issues/1430
	//
	// Check for driver.Valuer must come before json.Marshaler so that it is guaranteed to be used
	// when both are implemented https://github.com/jackc/pgx/issues/1805
	case driver.Valuer:
		return &encodePlanDriverValuer{m: , oid: , formatCode: }

	// Must come before trying wrap encode plans because a pointer to a struct may be unwrapped to a struct that can be
	// marshalled.
	//
	// https://github.com/jackc/pgx/issues/1681
	case json.Marshaler:
		return &encodePlanJSONCodecEitherFormatMarshal{
			marshal: .Marshal,
		}
	}

	// Because anything can be marshalled the normal wrapping in Map.PlanScan doesn't get a chance to run. So try the
	// appropriate wrappers here.
	for ,  := range []TryWrapEncodePlanFunc{
		TryWrapDerefPointerEncodePlan,
		TryWrapFindUnderlyingTypeEncodePlan,
	} {
		if , ,  := ();  {
			if  := .(, , , );  != nil {
				.SetNext()
				return 
			}
		}
	}

	return &encodePlanJSONCodecEitherFormatMarshal{
		marshal: .Marshal,
	}
}

// JSON needs its on scan plan for pointers to handle 'null'::json(b).
// Consider making pointerPointerScanPlan more flexible in the future.
type jsonPointerScanPlan struct {
	next ScanPlan
}

func ( jsonPointerScanPlan) ( []byte,  any) error {
	 := reflect.ValueOf().Elem()
	if  == nil || string() == "null" {
		.SetZero()
		return nil
	}

	.Set(reflect.New(.Type().Elem()))
	if .next != nil {
		return .next.Scan(, .Interface())
	}

	return nil
}

type encodePlanJSONCodecEitherFormatString struct{}

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

type encodePlanJSONCodecEitherFormatByteSlice struct{}

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

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

type encodePlanJSONCodecEitherFormatJSONRawMessage struct{}

func (encodePlanJSONCodecEitherFormatJSONRawMessage) ( any,  []byte) ( []byte,  error) {
	 := .(json.RawMessage)
	if  == nil {
		return nil, nil
	}

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

type encodePlanJSONCodecEitherFormatMarshal struct {
	marshal func(v any) ([]byte, error)
}

func ( *encodePlanJSONCodecEitherFormatMarshal) ( any,  []byte) ( []byte,  error) {
	,  := .marshal()
	if  != nil {
		return nil, 
	}

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

func ( *JSONCodec) ( *Map,  uint32,  int16,  any) ScanPlan {
	return .planScan(, , , , 0)
}

// JSON cannot fallback to pointerPointerScanPlan because of 'null'::json(b),
// so we need to duplicate the logic here.
func ( *JSONCodec) ( *Map,  uint32,  int16,  any,  int) ScanPlan {
	if  > 8 {
		return &scanPlanFail{m: , oid: , formatCode: }
	}

	switch .(type) {
	case *string:
		return &scanPlanAnyToString{}
	case *[]byte:
		return &scanPlanJSONToByteSlice{}
	case BytesScanner:
		return &scanPlanBinaryBytesToBytesScanner{}
	case sql.Scanner:
		return &scanPlanCodecSQLScanner{c: , m: , oid: , formatCode: }
	}

	 := reflect.ValueOf()
	if .Kind() == reflect.Pointer && .Elem().Kind() == reflect.Pointer {
		var  jsonPointerScanPlan
		.next = .(, , , .Elem().Interface(), +1)
		return 
	} else {
		return &scanPlanJSONToJSONUnmarshal{unmarshal: .Unmarshal}
	}
}

type scanPlanAnyToString struct{}

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

type scanPlanJSONToByteSlice struct{}

func (scanPlanJSONToByteSlice) ( []byte,  any) error {
	 := .(*[]byte)
	if  == nil {
		* = nil
		return nil
	}

	* = make([]byte, len())
	copy(*, )
	return nil
}

type scanPlanJSONToJSONUnmarshal struct {
	unmarshal func(data []byte, v any) error
}

func ( *scanPlanJSONToJSONUnmarshal) ( []byte,  any) error {
	if  == nil {
		 := reflect.ValueOf()
		if .Kind() == reflect.Ptr {
			 := .Elem()
			switch .Kind() {
			case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
				.Set(reflect.Zero(.Type()))
				return nil
			}
		}

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

	 := reflect.ValueOf()
	if .Kind() != reflect.Pointer || .IsNil() {
		return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", )
	}

	 := .Elem()
	.Set(reflect.Zero(.Type()))

	return .unmarshal(, )
}

func ( *JSONCodec) ( *Map,  uint32,  int16,  []byte) (driver.Value, error) {
	if  == nil {
		return nil, nil
	}

	 := make([]byte, len())
	copy(, )
	return , nil
}

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

	var  any
	 := .Unmarshal(, &)
	return , 
}