// Copyright 2010 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 (
	"bytes"
	"errors"
	"io"

	"encoding/json/jsontext"
	jsonv2 "encoding/json/v2"
)

// A Decoder reads and decodes JSON values from an input stream.
type Decoder struct {
	dec  *jsontext.Decoder
	opts jsonv2.Options
	err  error

	// hadPeeked reports whether [Decoder.More] was called.
	// It is reset by [Decoder.Decode] and [Decoder.Token].
	hadPeeked bool
}

// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder {
	// Hide bytes.Buffer from jsontext since it implements optimizations that
	// also limits certain ways it could be used. For example, one cannot write
	// to the bytes.Buffer while it is in use by jsontext.Decoder.
	if _, ok := r.(*bytes.Buffer); ok {
		r = struct{ io.Reader }{r}
	}

	dec := new(Decoder)
	dec.opts = DefaultOptionsV1()
	dec.dec = jsontext.NewDecoder(r, dec.opts)
	return dec
}

// UseNumber causes the Decoder to unmarshal a number into an
// interface value as a [Number] instead of as a float64.
func (dec *Decoder) UseNumber() {
	if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); !useNumber {
		dec.opts = jsonv2.JoinOptions(dec.opts, unmarshalAnyWithRawNumber(true))
	}
}

// DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
func (dec *Decoder) DisallowUnknownFields() {
	if reject, _ := jsonv2.GetOption(dec.opts, jsonv2.RejectUnknownMembers); !reject {
		dec.opts = jsonv2.JoinOptions(dec.opts, jsonv2.RejectUnknownMembers(true))
	}
}

// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
//
// See the documentation for [Unmarshal] for details about
// the conversion of JSON into a Go value.
func (dec *Decoder) Decode(v any) error {
	if dec.err != nil {
		return dec.err
	}
	b, err := dec.dec.ReadValue()
	if err != nil {
		dec.err = transformSyntacticError(err)
		if dec.err.Error() == errUnexpectedEnd.Error() {
			// NOTE: Decode has always been inconsistent with Unmarshal
			// with regard to the exact error value for truncated input.
			dec.err = io.ErrUnexpectedEOF
		}
		return dec.err
	}
	dec.hadPeeked = false
	return jsonv2.Unmarshal(b, v, dec.opts)
}

// Buffered returns a reader of the data remaining in the Decoder's
// buffer. The reader is valid until the next call to [Decoder.Decode].
func (dec *Decoder) Buffered() io.Reader {
	return bytes.NewReader(dec.dec.UnreadBuffer())
}

// An Encoder writes JSON values to an output stream.
type Encoder struct {
	w    io.Writer
	opts jsonv2.Options
	err  error

	buf       bytes.Buffer
	indentBuf bytes.Buffer

	indentPrefix string
	indentValue  string
}

// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
	enc := new(Encoder)
	enc.w = w
	enc.opts = DefaultOptionsV1()
	return enc
}

// Encode writes the JSON encoding of v to the stream,
// followed by a newline character.
//
// See the documentation for [Marshal] for details about the
// conversion of Go values to JSON.
func (enc *Encoder) Encode(v any) error {
	if enc.err != nil {
		return enc.err
	}

	buf := &enc.buf
	buf.Reset()
	if err := jsonv2.MarshalWrite(buf, v, enc.opts); err != nil {
		return err
	}
	if len(enc.indentPrefix)+len(enc.indentValue) > 0 {
		enc.indentBuf.Reset()
		if err := Indent(&enc.indentBuf, buf.Bytes(), enc.indentPrefix, enc.indentValue); err != nil {
			return err
		}
		buf = &enc.indentBuf
	}
	buf.WriteByte('\n')

	if _, err := enc.w.Write(buf.Bytes()); err != nil {
		enc.err = err
		return err
	}
	return nil
}

// SetIndent instructs the encoder to format each subsequent encoded
// value as if indented by the package-level function Indent(dst, src, prefix, indent).
// Calling SetIndent("", "") disables indentation.
func (enc *Encoder) SetIndent(prefix, indent string) {
	enc.indentPrefix = prefix
	enc.indentValue = indent
}

// SetEscapeHTML specifies whether problematic HTML characters
// should be escaped inside JSON quoted strings.
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
// to avoid certain safety problems that can arise when embedding JSON in HTML.
//
// In non-HTML settings where the escaping interferes with the readability
// of the output, SetEscapeHTML(false) disables this behavior.
func (enc *Encoder) SetEscapeHTML(on bool) {
	if escape, _ := jsonv2.GetOption(enc.opts, jsontext.EscapeForHTML); escape != on {
		enc.opts = jsonv2.JoinOptions(enc.opts, jsontext.EscapeForHTML(on))
	}
}

// RawMessage is a raw encoded JSON value.
// It implements [Marshaler] and [Unmarshaler] and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage = jsontext.Value

// A Token holds a value of one of these types:
//
//   - [Delim], for the four JSON delimiters [ ] { }
//   - bool, for JSON booleans
//   - float64, for JSON numbers
//   - [Number], for JSON numbers
//   - string, for JSON string literals
//   - nil, for JSON null
type Token any

// A Delim is a JSON array or object delimiter, one of [ ] { or }.
type Delim rune

func (d Delim) String() string {
	return string(d)
}

// Token returns the next JSON token in the input stream.
// At the end of the input stream, Token returns nil, [io.EOF].
//
// Token guarantees that the delimiters [ ] { } it returns are
// properly nested and matched: if Token encounters an unexpected
// delimiter in the input, it will return an error.
//
// The input stream consists of basic JSON values—bool, string,
// number, and null—along with delimiters [ ] { } of type [Delim]
// to mark the start and end of arrays and objects.
// Commas and colons are elided.
func (dec *Decoder) Token() (Token, error) {
	tok, err := dec.dec.ReadToken()
	if err != nil {
		// Historically, v1 would report just [io.EOF] if
		// the stream is a prefix of a valid JSON value.
		// It reports an unwrapped [io.ErrUnexpectedEOF] if
		// truncated within a JSON token such as a literal, number, or string.
		if errors.Is(err, io.ErrUnexpectedEOF) {
			if len(bytes.Trim(dec.dec.UnreadBuffer(), " \r\n\t,:")) == 0 {
				return nil, io.EOF
			}
			return nil, io.ErrUnexpectedEOF
		}
		return nil, transformSyntacticError(err)
	}
	dec.hadPeeked = false
	switch k := tok.Kind(); k {
	case 'n':
		return nil, nil
	case 'f':
		return false, nil
	case 't':
		return true, nil
	case '"':
		return tok.String(), nil
	case '0':
		if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); useNumber {
			return Number(tok.String()), nil
		}
		return tok.Float(), nil
	case '{', '}', '[', ']':
		return Delim(k), nil
	default:
		panic("unreachable")
	}
}

// More reports whether there is another element in the
// current array or object being parsed.
func (dec *Decoder) More() bool {
	dec.hadPeeked = true
	k := dec.dec.PeekKind()
	return k > 0 && k != ']' && k != '}'
}

// InputOffset returns the input stream byte offset of the current decoder position.
// The offset gives the location of the end of the most recently returned token
// and the beginning of the next token.
func (dec *Decoder) InputOffset() int64 {
	offset := dec.dec.InputOffset()
	if dec.hadPeeked {
		// Historically, InputOffset reported the location of
		// the end of the most recently returned token
		// unless [Decoder.More] is called, in which case, it reported
		// the beginning of the next token.
		unreadBuffer := dec.dec.UnreadBuffer()
		trailingTokens := bytes.TrimLeft(unreadBuffer, " \n\r\t")
		if len(trailingTokens) > 0 {
			leadingWhitespace := len(unreadBuffer) - len(trailingTokens)
			offset += int64(leadingWhitespace)
		}
	}
	return offset
}
