// 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 jsonopts

import (
	"encoding/json/internal"
	"encoding/json/internal/jsonflags"
)

// Options is the common options type shared across json packages.
type Options interface {
	// JSONOptions is exported so related json packages can implement Options.
	JSONOptions(internal.NotForPublicUse)
}

// experimentalFormatTagSupporter is a special option method that allows
// [github.com/go-json-experiment/json.ExperimentalSupportFormatTag]
// to enable experimental `format` tag functionality at runtime.
type experimentalFormatTagSupporter interface{ ExperimentalSupportFormatTag() bool }

// Struct is the combination of all options in struct form.
// This is efficient to pass down the call stack and to query.
type Struct struct {
	Flags jsonflags.Flags

	CoderValues
	ArshalValues
}

type CoderValues struct {
	Indent       string // jsonflags.Indent
	IndentPrefix string // jsonflags.IndentPrefix
	ByteLimit    int64  // jsonflags.ByteLimit
	DepthLimit   int    // jsonflags.DepthLimit
}

type ArshalValues struct {
	// The Marshalers and Unmarshalers fields use the any type to avoid a
	// concrete dependency on *json.Marshalers and *json.Unmarshalers,
	// which would in turn create a dependency on the "reflect" package.

	Marshalers   any // jsonflags.Marshalers
	Unmarshalers any // jsonflags.Unmarshalers

	Format string // valid if jsonflags.FormatTag is set
}

// DefaultOptionsV2 is the set of all options that define default v2 behavior.
var DefaultOptionsV2 = Struct{
	Flags: jsonflags.Flags{
		Presence: uint64(jsonflags.DefaultV1Flags),
		Values:   uint64(0), // all flags in DefaultV1Flags are false
	},
}

// DefaultOptionsV1 is the set of all options that define default v1 behavior.
var DefaultOptionsV1 = Struct{
	Flags: jsonflags.Flags{
		Presence: uint64(jsonflags.DefaultV1Flags),
		Values:   uint64(jsonflags.DefaultV1Flags), // all flags in DefaultV1Flags are true
	},
}

func (*Struct) JSONOptions(internal.NotForPublicUse) {}

// GetUnknownOption is injected by the "json" package to handle Options
// declared in that package so that "jsonopts" can handle them.
var GetUnknownOption = func(Struct, Options) (any, bool) { panic("unknown option") }

func GetOption[T any](opts Options, setter func(T) Options) (T, bool) {
	// Collapse the options to *Struct to simplify lookup.
	structOpts, ok := opts.(*Struct)
	if !ok {
		var structOpts2 Struct
		structOpts2.Join(opts)
		structOpts = &structOpts2
	}

	// Lookup the option based on the return value of the setter.
	var zero T
	switch opt := setter(zero).(type) {
	case jsonflags.Bools:
		v := structOpts.Flags.Get(opt)
		ok := structOpts.Flags.Has(opt)
		if !ok && opt == jsonflags.StringifyNumbers && structOpts.Flags.Get(jsonflags.StringTag) {
			return any(true).(T), true // check also whether the option is specified via a `string` tag
		}
		return any(v).(T), ok
	case experimentalFormatTagSupporter:
		v := structOpts.Flags.Get(jsonflags.FormatTagSupported)
		ok := structOpts.Flags.Has(jsonflags.FormatTagSupported)
		return any(v).(T), ok
	case Indent:
		if !structOpts.Flags.Has(jsonflags.Indent) {
			return zero, false
		}
		return any(structOpts.Indent).(T), true
	case IndentPrefix:
		if !structOpts.Flags.Has(jsonflags.IndentPrefix) {
			return zero, false
		}
		return any(structOpts.IndentPrefix).(T), true
	case ByteLimit:
		if !structOpts.Flags.Has(jsonflags.ByteLimit) {
			return zero, false
		}
		return any(structOpts.ByteLimit).(T), true
	case DepthLimit:
		if !structOpts.Flags.Has(jsonflags.DepthLimit) {
			return zero, false
		}
		return any(structOpts.DepthLimit).(T), true
	default:
		v, ok := GetUnknownOption(*structOpts, opt)
		return v.(T), ok
	}
}

// JoinUnknownOption is injected by the "json" package to handle Options
// declared in that package so that "jsonopts" can handle them.
var JoinUnknownOption = func(Struct, Options) Struct { panic("unknown option") }

func (dst *Struct) Join(srcs ...Options) {
	for _, src := range srcs {
		switch src := src.(type) {
		case nil:
			continue
		case jsonflags.Bools:
			dst.Flags.Set(src)
		case experimentalFormatTagSupporter:
			if src.ExperimentalSupportFormatTag() {
				dst.Flags.Set(jsonflags.FormatTagSupported | 1)
			} else {
				dst.Flags.Set(jsonflags.FormatTagSupported | 0)
			}
		case Indent:
			dst.Flags.Set(jsonflags.Multiline | jsonflags.Indent | 1)
			dst.Indent = string(src)
		case IndentPrefix:
			dst.Flags.Set(jsonflags.Multiline | jsonflags.IndentPrefix | 1)
			dst.IndentPrefix = string(src)
		case ByteLimit:
			dst.Flags.Set(jsonflags.ByteLimit | 1)
			dst.ByteLimit = int64(src)
		case DepthLimit:
			dst.Flags.Set(jsonflags.DepthLimit | 1)
			dst.DepthLimit = int(src)
		case *Struct:
			dst.Flags.Join(src.Flags)
			if src.Flags.Has(jsonflags.NonBooleanFlags) {
				if src.Flags.Has(jsonflags.Indent) {
					dst.Indent = src.Indent
				}
				if src.Flags.Has(jsonflags.IndentPrefix) {
					dst.IndentPrefix = src.IndentPrefix
				}
				if src.Flags.Has(jsonflags.ByteLimit) {
					dst.ByteLimit = src.ByteLimit
				}
				if src.Flags.Has(jsonflags.DepthLimit) {
					dst.DepthLimit = src.DepthLimit
				}
				if src.Flags.Has(jsonflags.Marshalers) {
					dst.Marshalers = src.Marshalers
				}
				if src.Flags.Has(jsonflags.Unmarshalers) {
					dst.Unmarshalers = src.Unmarshalers
				}
				if src.Flags.Has(jsonflags.FormatTag) {
					dst.Format = src.Format
				}
			}
		default:
			*dst = JoinUnknownOption(*dst, src)
		}
	}
}

// InitializeMultiline sets default options implied by Multiline.
func (s *Struct) InitializeMultiline() {
	if !s.Flags.Has(jsonflags.SpaceAfterColon) {
		s.Flags.Set(jsonflags.SpaceAfterColon | 1)
	}
	if !s.Flags.Has(jsonflags.SpaceAfterComma) {
		s.Flags.Set(jsonflags.SpaceAfterComma | 0)
	}
	if !s.Flags.Has(jsonflags.Indent) {
		s.Flags.Set(jsonflags.Indent | 1)
		s.Indent = "\t"
	}
}

// ChangedWhitespace reports whether whitespace values have changed.
func ChangedWhitespace(s1, s2 Struct) bool {
	return s1.Flags.Get(jsonflags.Multiline) != s2.Flags.Get(jsonflags.Multiline) ||
		s1.Flags.Get(jsonflags.SpaceAfterColon) != s2.Flags.Get(jsonflags.SpaceAfterColon) ||
		s1.Flags.Get(jsonflags.SpaceAfterComma) != s2.Flags.Get(jsonflags.SpaceAfterComma) ||
		(s2.Flags.Get(jsonflags.Multiline) && (s1.Indent != s2.Indent || s1.IndentPrefix != s2.IndentPrefix))
}

type (
	Indent       string // jsontext.WithIndent
	IndentPrefix string // jsontext.WithIndentPrefix
	ByteLimit    int64  // jsontext.WithByteLimit
	DepthLimit   int    // jsontext.WithDepthLimit
	// type for jsonflags.Marshalers declared in "json" package
	// type for jsonflags.Unmarshalers declared in "json" package
)

func (Indent) JSONOptions(internal.NotForPublicUse)       {}
func (IndentPrefix) JSONOptions(internal.NotForPublicUse) {}
func (ByteLimit) JSONOptions(internal.NotForPublicUse)    {}
func (DepthLimit) JSONOptions(internal.NotForPublicUse)   {}
