// Copyright 2018 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.

package text

import (
	"bytes"
	"strings"

	"github.com/golang/protobuf/v2/internal/detrand"
	"github.com/golang/protobuf/v2/internal/errors"
)

// Marshal serializes v as the proto text format, where v must be a Message.
// In the proto text format, the top-level value is always a message where the
// delimiters are elided.
//
// If indent is a non-empty string, it causes every entry in a List or Message
// to be preceded by the indent and trailed by a newline.
//
// If delims is not the zero value, it controls the delimiter characters used
// for messages (e.g., "{}" vs "<>").
//
// If outputASCII is true, strings will be serialized in such a way that
// multi-byte UTF-8 sequences are escaped. This property ensures that the
// overall output is ASCII (as opposed to UTF-8).
func Marshal(v Value, indent string, delims [2]byte, outputASCII bool) ([]byte, error) {
	p := encoder{}
	if len(indent) > 0 {
		if strings.Trim(indent, " \t") != "" {
			return nil, errors.New("indent may only be composed of space and tab characters")
		}
		p.indent = indent
		p.newline = "\n"
	}
	switch delims {
	case [2]byte{0, 0}:
		p.delims = [2]byte{'{', '}'}
	case [2]byte{'{', '}'}, [2]byte{'<', '>'}:
		p.delims = delims
	default:
		return nil, errors.New("delimiters may only be \"{}\" or \"<>\"")
	}
	p.outputASCII = outputASCII

	err := p.marshalMessage(v, false)
	if !p.nerr.Merge(err) {
		return nil, err
	}
	if len(indent) > 0 {
		return append(bytes.TrimRight(p.out, "\n"), '\n'), p.nerr.E
	}
	return p.out, p.nerr.E
}

type encoder struct {
	nerr errors.NonFatal
	out  []byte

	indent      string
	indents     []byte
	newline     string // set to "\n" if len(indent) > 0
	delims      [2]byte
	outputASCII bool
}

func (p *encoder) marshalList(v Value) error {
	if v.Type() != List {
		return errors.New("invalid type %v, expected list", v.Type())
	}
	elems := v.List()
	p.out = append(p.out, '[')
	p.indents = append(p.indents, p.indent...)
	if len(elems) > 0 {
		p.out = append(p.out, p.newline...)
	}
	for i, elem := range elems {
		p.out = append(p.out, p.indents...)
		if err := p.marshalValue(elem); !p.nerr.Merge(err) {
			return err
		}
		if i < len(elems)-1 {
			p.out = append(p.out, ',')
		}
		p.out = append(p.out, p.newline...)
	}
	p.indents = p.indents[:len(p.indents)-len(p.indent)]
	if len(elems) > 0 {
		p.out = append(p.out, p.indents...)
	}
	p.out = append(p.out, ']')
	return nil
}

func (p *encoder) marshalMessage(v Value, emitDelims bool) error {
	if v.Type() != Message {
		return errors.New("invalid type %v, expected message", v.Type())
	}
	items := v.Message()
	if emitDelims {
		p.out = append(p.out, p.delims[0])
		p.indents = append(p.indents, p.indent...)
		if len(items) > 0 {
			p.out = append(p.out, p.newline...)
		}
	}
	for i, item := range items {
		p.out = append(p.out, p.indents...)
		if err := p.marshalKey(item[0]); !p.nerr.Merge(err) {
			return err
		}
		p.out = append(p.out, ':')
		if len(p.indent) > 0 {
			p.out = append(p.out, ' ')
		}
		// For multi-line output, add a random extra space after key: per message to
		// make output unstable.
		if len(p.indent) > 0 && detrand.Bool() {
			p.out = append(p.out, ' ')
		}

		if err := p.marshalValue(item[1]); !p.nerr.Merge(err) {
			return err
		}
		if i < len(items)-1 && len(p.indent) == 0 {
			p.out = append(p.out, ' ')
		}
		// For single-line output, add a random extra space after a field per message to
		// make output unstable.
		if len(p.indent) == 0 && detrand.Bool() && i != len(items)-1 {
			p.out = append(p.out, ' ')
		}
		p.out = append(p.out, p.newline...)
	}
	if emitDelims {
		p.indents = p.indents[:len(p.indents)-len(p.indent)]
		if len(items) > 0 {
			p.out = append(p.out, p.indents...)
		}
		p.out = append(p.out, p.delims[1])
	}
	return nil
}

func (p *encoder) marshalKey(v Value) error {
	switch v.Type() {
	case String:
		var err error
		p.out = append(p.out, '[')
		if len(urlRegexp.FindString(v.str)) == len(v.str) {
			p.out = append(p.out, v.str...)
		} else {
			err = p.marshalString(v)
		}
		p.out = append(p.out, ']')
		return err
	case Uint:
		return p.marshalNumber(v)
	case Name:
		s, _ := v.Name()
		p.out = append(p.out, s...)
		return nil
	default:
		return errors.New("invalid type %v to encode key", v.Type())
	}
}

func (p *encoder) marshalValue(v Value) error {
	switch v.Type() {
	case Bool, Int, Uint, Float:
		return p.marshalNumber(v)
	case String:
		return p.marshalString(v)
	case List:
		return p.marshalList(v)
	case Message:
		return p.marshalMessage(v, true)
	case Name:
		s, _ := v.Name()
		p.out = append(p.out, s...)
		return nil
	default:
		return errors.New("invalid type %v to encode value", v.Type())
	}
}
