// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build goexperiment.jsonv2

package json

import (
	"encoding"
	"errors"
	"io"
	"reflect"

	"encoding/json/internal"
	"encoding/json/internal/jsonflags"
	"encoding/json/internal/jsonopts"
	"encoding/json/internal/jsonwire"
	"encoding/json/jsontext"
)

var errNonStringValue = errors.New("JSON value must be string type")

// Interfaces for custom serialization.
var (
	jsonMarshalerType       = reflect.TypeFor[Marshaler]()
	jsonMarshalerToType     = reflect.TypeFor[MarshalerTo]()
	jsonUnmarshalerType     = reflect.TypeFor[Unmarshaler]()
	jsonUnmarshalerFromType = reflect.TypeFor[UnmarshalerFrom]()
	textAppenderType        = reflect.TypeFor[encoding.TextAppender]()
	textMarshalerType       = reflect.TypeFor[encoding.TextMarshaler]()
	textUnmarshalerType     = reflect.TypeFor[encoding.TextUnmarshaler]()

	allMarshalerTypes   = []reflect.Type{jsonMarshalerToType, jsonMarshalerType, textAppenderType, textMarshalerType}
	allUnmarshalerTypes = []reflect.Type{jsonUnmarshalerFromType, jsonUnmarshalerType, textUnmarshalerType}
	allMethodTypes      = append(allMarshalerTypes, allUnmarshalerTypes...)
)

// Marshaler is implemented by types that can marshal themselves.
// It is recommended that types implement [MarshalerTo] unless the implementation
// is trying to avoid a hard dependency on the "jsontext" package.
//
// It is recommended that implementations return a buffer that is safe
// for the caller to retain and potentially mutate.
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError].
type Marshaler interface {
	MarshalJSON() ([]byte, error)
}

// MarshalerTo is implemented by types that can marshal themselves.
// It is recommended that types implement MarshalerTo instead of [Marshaler]
// since this is both more performant and flexible.
// If a type implements both Marshaler and MarshalerTo,
// then MarshalerTo takes precedence. In such a case, both implementations
// should aim to have equivalent behavior for the default marshal options.
//
// The implementation must write only one JSON value to the Encoder.
// Alternatively, it may return [errors.ErrUnsupported] without mutating
// the Encoder. The "json" package calling the method will
// use the next available JSON representation for the receiver type.
// Implementations must not retain the pointer to [jsontext.Encoder].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError],
// unless it is an IO error.
//
// The MarshalJSONTo method should not be directly called as it may
// return sentinel errors that need special handling.
// Users should instead call [MarshalEncode], which handles such cases.
type MarshalerTo interface {
	MarshalJSONTo(*jsontext.Encoder) error
}

// Unmarshaler is implemented by types that can unmarshal themselves.
// It is recommended that types implement [UnmarshalerFrom] unless the implementation
// is trying to avoid a hard dependency on the "jsontext" package.
//
// The input can be assumed to be a valid encoding of a JSON value
// if called from unmarshal functionality in this package.
// UnmarshalJSON must copy the JSON data if it is retained after returning.
// It is recommended that UnmarshalJSON implement merge semantics when
// unmarshaling into a pre-populated value.
//
// Implementations must not retain or mutate the input []byte.
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError].
type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}

// UnmarshalerFrom is implemented by types that can unmarshal themselves.
// It is recommended that types implement UnmarshalerFrom instead of [Unmarshaler]
// since this is both more performant and flexible.
// If a type implements both Unmarshaler and UnmarshalerFrom,
// then UnmarshalerFrom takes precedence. In such a case, both implementations
// should aim to have equivalent behavior for the default unmarshal options.
//
// The implementation must read only one JSON value from the Decoder.
// It is recommended that UnmarshalJSONFrom implement merge semantics when
// unmarshaling into a pre-populated value.
// Alternatively, it may return [errors.ErrUnsupported] without mutating
// the Decoder. The "json" package calling the method will
// use the next available JSON representation for the receiver type.
// Implementations must not retain the pointer to [jsontext.Decoder].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError],
// unless it is a [jsontext.SyntacticError] or an IO error.
//
// The UnmarshalJSONFrom method should not be directly called as it may
// return sentinel errors that need special handling.
// Users should instead call [UnmarshalDecode], which handles such cases.
type UnmarshalerFrom interface {
	UnmarshalJSONFrom(*jsontext.Decoder) error
}

func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
	// Avoid injecting method arshaler on the pointer or interface version
	// to avoid ever calling the method on a nil pointer or interface receiver.
	// Let it be injected on the value receiver (which is always addressable).
	if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
		return fncs
	}

	if needAddr, ok := implements(t, textMarshalerType); ok {
		fncs.nonDefault = true
		prevMarshal := fncs.marshal
		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(needAddr && va.forcedAddr) {
				return prevMarshal(enc, va, mo)
			}
			marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
			if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
				b2, err := marshaler.MarshalText()
				return append(b, b2...), err
			}); err != nil {
				err = wrapErrUnsupported(err, "MarshalText method")
				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText") // unlike unmarshal, always wrapped
				}
				if !isSemanticError(err) && !export.IsIOError(err) {
					err = newMarshalErrorBefore(enc, t, err)
				}
				return err
			}
			return nil
		}
	}

	if needAddr, ok := implements(t, textAppenderType); ok {
		fncs.nonDefault = true
		prevMarshal := fncs.marshal
		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(needAddr && va.forcedAddr) {
				return prevMarshal(enc, va, mo)
			}
			appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
			if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
				err = wrapErrUnsupported(err, "AppendText method")
				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText") // unlike unmarshal, always wrapped
				}
				if !isSemanticError(err) && !export.IsIOError(err) {
					err = newMarshalErrorBefore(enc, t, err)
				}
				return err
			}
			return nil
		}
	}

	if needAddr, ok := implements(t, jsonMarshalerType); ok {
		fncs.nonDefault = true
		prevMarshal := fncs.marshal
		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
				return prevMarshal(enc, va, mo)
			}
			marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
			val, err := marshaler.MarshalJSON()
			if err != nil {
				err = wrapErrUnsupported(err, "MarshalJSON method")
				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
				}
				err = newMarshalErrorBefore(enc, t, err)
				return collapseSemanticErrors(err)
			}
			if err := enc.WriteValue(val); err != nil {
				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
				}
				if isSyntacticError(err) {
					err = newMarshalErrorBefore(enc, t, err)
				}
				return err
			}
			return nil
		}
	}

	if needAddr, ok := implements(t, jsonMarshalerToType); ok {
		fncs.nonDefault = true
		prevMarshal := fncs.marshal
		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
				return prevMarshal(enc, va, mo)
			}
			xe := export.Encoder(enc)
			prevDepth, prevLength := xe.Tokens.DepthLength()
			xe.Flags.Set(jsonflags.WithinArshalCall | 1)
			marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
			err := marshaler.MarshalJSONTo(enc)
			xe.Flags.Set(jsonflags.WithinArshalCall | 0)
			currDepth, currLength := xe.Tokens.DepthLength()
			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
				err = errNonSingularValue
			}
			if err != nil {
				if errors.Is(err, errors.ErrUnsupported) {
					if prevDepth == currDepth && prevLength == currLength {
						return prevMarshal(enc, va, mo)
					}
					err = errUnsupportedMutation
				}
				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo") // unlike unmarshal, always wrapped
				}
				if !export.IsIOError(err) {
					err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
				}
				return err
			}
			return nil
		}
	}

	if _, ok := implements(t, textUnmarshalerType); ok {
		fncs.nonDefault = true
		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
			xd := export.Decoder(dec)
			var flags jsonwire.ValueFlags
			val, err := xd.ReadValue(&flags)
			if err != nil {
				return err // must be a syntactic or I/O error
			}
			if val.Kind() == 'n' {
				if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
					va.SetZero()
				}
				return nil
			}
			if val.Kind() != '"' {
				return newUnmarshalErrorAfter(dec, t, errNonStringValue)
			}
			s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
			if err := unmarshaler.UnmarshalText(s); err != nil {
				err = wrapErrUnsupported(err, "UnmarshalText method")
				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return err // unlike marshal, never wrapped
				}
				if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
					err = newUnmarshalErrorAfter(dec, t, err)
				}
				return err
			}
			return nil
		}
	}

	if _, ok := implements(t, jsonUnmarshalerType); ok {
		fncs.nonDefault = true
		prevUnmarshal := fncs.unmarshal
		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				export.Decoder(dec).Tokens.Last.NeedObjectName() {
				return prevUnmarshal(dec, va, uo)
			}
			val, err := dec.ReadValue()
			if err != nil {
				return err // must be a syntactic or I/O error
			}
			unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
			if err := unmarshaler.UnmarshalJSON(val); err != nil {
				err = wrapErrUnsupported(err, "UnmarshalJSON method")
				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return err // unlike marshal, never wrapped
				}
				err = newUnmarshalErrorAfter(dec, t, err)
				return collapseSemanticErrors(err)
			}
			return nil
		}
	}

	if _, ok := implements(t, jsonUnmarshalerFromType); ok {
		fncs.nonDefault = true
		prevUnmarshal := fncs.unmarshal
		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				export.Decoder(dec).Tokens.Last.NeedObjectName() {
				return prevUnmarshal(dec, va, uo)
			}
			xd := export.Decoder(dec)
			prevDepth, prevLength := xd.Tokens.DepthLength()
			if prevDepth == 1 && xd.AtEOF() {
				return io.EOF // check EOF early to avoid fn reporting an EOF
			}
			xd.Flags.Set(jsonflags.WithinArshalCall | 1)
			unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
			err := unmarshaler.UnmarshalJSONFrom(dec)
			xd.Flags.Set(jsonflags.WithinArshalCall | 0)
			currDepth, currLength := xd.Tokens.DepthLength()
			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
				err = errNonSingularValue
			}
			if err != nil {
				if errors.Is(err, errors.ErrUnsupported) {
					if prevDepth == currDepth && prevLength == currLength {
						return prevUnmarshal(dec, va, uo)
					}
					err = errUnsupportedMutation
				}
				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
						return err2
					}
					return err // unlike marshal, never wrapped
				}
				if !isSyntacticError(err) && !export.IsIOError(err) {
					err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
				}
				return err
			}
			return nil
		}
	}

	return fncs
}

// implementsAny is like t.Implements(ifaceType) for a list of interfaces,
// but checks whether either t or reflect.PointerTo(t) implements the interface.
func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
	for _, ifaceType := range ifaceTypes {
		if _, ok := implements(t, ifaceType); ok {
			return true
		}
	}
	return false
}

// implements is like t.Implements(ifaceType) but checks whether
// either t or reflect.PointerTo(t) implements the interface.
// It also reports whether the value needs to be addressed
// in order to satisfy the interface.
func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
	switch {
	case t.Implements(ifaceType):
		return false, true
	case reflect.PointerTo(t).Implements(ifaceType):
		return true, true
	default:
		return false, false
	}
}
