// Copyright 2023 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 (
	"fmt"

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

// Options configure [Marshal], [MarshalWrite], [MarshalEncode],
// [Unmarshal], [UnmarshalRead], and [UnmarshalDecode] with specific features.
// Each function takes in a variadic list of options, where properties
// set in later options override the value of previously set properties.
//
// The Options type is identical to [encoding/json.Options] and
// [encoding/json/jsontext.Options]. Options from the other packages can
// be used interchangeably with functionality in this package.
//
// An Options value represents either a single option or a set of options.
// It can be thought of as a Go map of option properties
// (even though the underlying implementation avoids Go maps for performance).
//
// The constructors (e.g., [Deterministic]) return a value for a single option:
//
//	opt := Deterministic(true)
//
// which is analogous to creating a single entry map:
//
//	opt := Options{"Deterministic": true}
//
// [JoinOptions] composes multiple options values together:
//
//	out := JoinOptions(opts...)
//
// which is analogous to making a new map and copying the options over:
//
//	out := make(Options)
//	for _, m := range opts {
//		for k, v := range m {
//			out[k] = v
//		}
//	}
//
// [GetOption] looks up the value of an options parameter:
//
//	v, ok := GetOption(opts, Deterministic)
//
// which is analogous to a Go map lookup:
//
//	v, ok := Options["Deterministic"]
//
// There is a single Options type, which is used with both marshal and unmarshal.
// Some options affect both operations, while others only affect one operation:
//
//   - [StringifyNumbers] affects marshaling and unmarshaling
//   - [Deterministic] affects marshaling only
//   - [FormatNilSliceAsNull] affects marshaling only
//   - [FormatNilMapAsNull] affects marshaling only
//   - [OmitZeroStructFields] affects marshaling only
//   - [MatchCaseInsensitiveNames] affects marshaling and unmarshaling
//   - [RejectUnknownMembers] affects unmarshaling only
//   - [WithMarshalers] affects marshaling only
//   - [WithUnmarshalers] affects unmarshaling only
//
// Options that do not affect a particular operation are ignored.
type Options = jsonopts.Options

// JoinOptions coalesces the provided list of options into a single Options.
// Properties set in later options override the value of previously set properties.
func JoinOptions(srcs ...Options) Options {
	var dst jsonopts.Struct
	dst.Join(srcs...)
	return &dst
}

// GetOption returns the value stored in opts with the provided setter,
// reporting whether the value is present.
// If not present, the returned value is the zero value for type T.
//
// Example usage:
//
//	v, ok := json.GetOption(opts, json.Deterministic)
//
// Options are most commonly introspected to alter the JSON representation of
// [MarshalerTo.MarshalJSONTo] and [UnmarshalerFrom.UnmarshalJSONFrom] methods, and
// [MarshalToFunc] and [UnmarshalFromFunc] functions.
// In such cases, the presence bit should generally be ignored.
func GetOption[T any](opts Options, setter func(T) Options) (T, bool) {
	return jsonopts.GetOption(opts, setter)
}

// DefaultOptionsV2 is the full set of all options that define v2 semantics.
// It is equivalent to the set of options in [encoding/json.DefaultOptionsV1]
// all being set to false. All other options are not present.
func DefaultOptionsV2() Options {
	return &jsonopts.DefaultOptionsV2
}

// StringifyNumbers specifies that types that would normally be
// encoded as a JSON number instead be encoded as a JSON string
// containing the equivalent JSON number value.
// When unmarshaling, the value is parsed from a JSON string
// containing the JSON number without any surrounding whitespace.
//
// Specifying the `string` tag option on a Go struct field applies this option
// to the top-level JSON value for that field. When applied via the `string`
// tag option, StringifyNumbers option does not recursively apply to nested
// JSON numbers within a JSON object or array.
//
// Like all options, explicitly specifying this option in a call to [Marshal],
// [Unmarshal], etc, will apply recursively.
//
// A Go type with custom marshal/unmarshal that represents a JSON number
// should respect the StringifyNumbers option and if specified
// serialize as a JSON number within a JSON string.
// Custom marshal/unmarshal should handle nested JSON objects using
// [MarshalEncode]/[UnmarshalDecode], which will automatically apply the
// non-recursive `string` tag option behavior.
//
// According to RFC 8259, section 6, a JSON implementation may choose to
// limit the representation of a JSON number to an IEEE 754 binary64 value.
// This may cause decoders to lose precision for int64 and uint64 types.
// Quoting JSON numbers as a JSON string preserves the exact precision.
//
// This affects either marshaling or unmarshaling.
func StringifyNumbers(v bool) Options {
	if v {
		return jsonflags.StringifyNumbers | 1
	} else {
		return jsonflags.StringifyNumbers | 0
	}
}

// Deterministic specifies that marshaling the same input value will always
// serialize as the same output bytes.
//
// For example, Go maps are marshaled sorted by key.
//
// For native Go types, Determinism is guaranteed across different instances of
// identical binaries, but not across different builds of a program (such as
// different source or toolchain version, different GOOS/GOARCH, different
// build flags).
//
// A Go type with a custom marshaler should also respect the Deterministic
// option and serialize deterministically if it is true.
//
// This only affects marshaling and is ignored when unmarshaling.
func Deterministic(v bool) Options {
	if v {
		return jsonflags.Deterministic | 1
	} else {
		return jsonflags.Deterministic | 0
	}
}

// FormatNilSliceAsNull specifies that a nil Go slice should marshal as a
// JSON null instead of the default representation as an empty JSON array
// (or an empty JSON string in the case of ~[]byte).
//
// This only affects marshaling and is ignored when unmarshaling.
func FormatNilSliceAsNull(v bool) Options {
	if v {
		return jsonflags.FormatNilSliceAsNull | 1
	} else {
		return jsonflags.FormatNilSliceAsNull | 0
	}
}

// FormatNilMapAsNull specifies that a nil Go map should marshal as a
// JSON null instead of the default representation as an empty JSON object.
//
// This only affects marshaling and is ignored when unmarshaling.
func FormatNilMapAsNull(v bool) Options {
	if v {
		return jsonflags.FormatNilMapAsNull | 1
	} else {
		return jsonflags.FormatNilMapAsNull | 0
	}
}

// OmitZeroStructFields specifies that zero-valued fields of Go struct should be
// omitted from the marshaled output.
// A value is considered zero if its type has an "IsZero() bool" method that returns true,
// or if it lacks such a method and the value is a Go zero value.
// This option is equivalent to specifying the `omitzero` tag option
// on every field in a Go struct.
//
// This only affects marshaling and is ignored when unmarshaling.
func OmitZeroStructFields(v bool) Options {
	if v {
		return jsonflags.OmitZeroStructFields | 1
	} else {
		return jsonflags.OmitZeroStructFields | 0
	}
}

// MatchCaseInsensitiveNames specifies that JSON object members are matched
// against Go struct fields using a case-insensitive match of the name.
// If a name matches multiple fields, the field whose name matches exactly is chosen.
// If there is none, an error is reported.
// Go struct fields explicitly marked with `case:strict` or `case:ignore`
// always use case-sensitive (or case-insensitive) name matching,
// regardless of the value of this option.
//
// This affects either marshaling or unmarshaling.
//
// Matching names case-insensitively also affects duplicate name detection
// (assuming [jsontext.AllowDuplicateNames] is false) since
// variations of the same name may match the same Go struct field.
// For example, when unmarshaling, the names "foo" and "Foo" may both
// match the same Go struct field and therefore be considered a duplicate name.
// When marshaling, normally it is impossible for any two Go struct fields to
// serialize in a way where they unmarshal into the same Go struct field
// since they all have unique exact names.
// However, it is possible for an
// embedded fallback to contain a name that also matches the name for
// a Go struct field, resulting in a duplicate name error.
func MatchCaseInsensitiveNames(v bool) Options {
	if v {
		return jsonflags.MatchCaseInsensitiveNames | 1
	} else {
		return jsonflags.MatchCaseInsensitiveNames | 0
	}
}

// RejectUnknownMembers specifies that unknown members should be rejected
// when unmarshaling a JSON object.
//
// This only affects unmarshaling and is ignored when marshaling.
func RejectUnknownMembers(v bool) Options {
	if v {
		return jsonflags.RejectUnknownMembers | 1
	} else {
		return jsonflags.RejectUnknownMembers | 0
	}
}

// WithMarshalers specifies a list of type-specific marshalers to use,
// which can be used to override the default marshal behavior for values
// of particular types.
//
// This only affects marshaling and is ignored when unmarshaling.
func WithMarshalers(v *Marshalers) Options {
	return (*marshalersOption)(v)
}

// WithUnmarshalers specifies a list of type-specific unmarshalers to use,
// which can be used to override the default unmarshal behavior for values
// of particular types.
//
// This only affects unmarshaling and is ignored when marshaling.
func WithUnmarshalers(v *Unmarshalers) Options {
	return (*unmarshalersOption)(v)
}

// These option types are declared here instead of "jsonopts"
// to avoid a dependency on "reflect" from "jsonopts".
type (
	marshalersOption   Marshalers
	unmarshalersOption Unmarshalers
)

func (*marshalersOption) JSONOptions(internal.NotForPublicUse)   {}
func (*unmarshalersOption) JSONOptions(internal.NotForPublicUse) {}

// Inject support into "jsonopts" to handle these types.
func init() {
	jsonopts.GetUnknownOption = func(src jsonopts.Struct, zero jsonopts.Options) (any, bool) {
		switch zero.(type) {
		case *marshalersOption:
			if !src.Flags.Has(jsonflags.Marshalers) {
				return (*Marshalers)(nil), false
			}
			return src.Marshalers.(*Marshalers), true
		case *unmarshalersOption:
			if !src.Flags.Has(jsonflags.Unmarshalers) {
				return (*Unmarshalers)(nil), false
			}
			return src.Unmarshalers.(*Unmarshalers), true
		default:
			panic(fmt.Sprintf("unknown option %T", zero))
		}
	}
	jsonopts.JoinUnknownOption = func(dst jsonopts.Struct, src jsonopts.Options) jsonopts.Struct {
		switch src := src.(type) {
		case *marshalersOption:
			dst.Flags.Set(jsonflags.Marshalers | 1)
			dst.Marshalers = (*Marshalers)(src)
		case *unmarshalersOption:
			dst.Flags.Set(jsonflags.Unmarshalers | 1)
			dst.Unmarshalers = (*Unmarshalers)(src)
		default:
			panic(fmt.Sprintf("unknown option %T", src))
		}
		return dst
	}
}
