// 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 descfmt provides functionality to format descriptors.
package descfmt

import (
	"fmt"
	"io"
	"reflect"
	"strconv"
	"strings"

	"google.golang.org/protobuf/internal/detrand"
	"google.golang.org/protobuf/internal/pragma"
	"google.golang.org/protobuf/reflect/protoreflect"
)

type list interface {
	Len() int
	pragma.DoNotImplement
}

func FormatList(s fmt.State, r rune, vs list) {
	io.WriteString(s, formatListOpt(vs, true, r == 'v' && (s.Flag('+') || s.Flag('#'))))
}
func formatListOpt(vs list, isRoot, allowMulti bool) string {
	start, end := "[", "]"
	if isRoot {
		var name string
		switch vs.(type) {
		case protoreflect.Names:
			name = "Names"
		case protoreflect.FieldNumbers:
			name = "FieldNumbers"
		case protoreflect.FieldRanges:
			name = "FieldRanges"
		case protoreflect.EnumRanges:
			name = "EnumRanges"
		case protoreflect.FileImports:
			name = "FileImports"
		case protoreflect.Descriptor:
			name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s"
		default:
			name = reflect.ValueOf(vs).Elem().Type().Name()
		}
		start, end = name+"{", "}"
	}

	var ss []string
	switch vs := vs.(type) {
	case protoreflect.Names:
		for i := 0; i < vs.Len(); i++ {
			ss = append(ss, fmt.Sprint(vs.Get(i)))
		}
		return start + joinStrings(ss, false) + end
	case protoreflect.FieldNumbers:
		for i := 0; i < vs.Len(); i++ {
			ss = append(ss, fmt.Sprint(vs.Get(i)))
		}
		return start + joinStrings(ss, false) + end
	case protoreflect.FieldRanges:
		for i := 0; i < vs.Len(); i++ {
			r := vs.Get(i)
			if r[0]+1 == r[1] {
				ss = append(ss, fmt.Sprintf("%d", r[0]))
			} else {
				ss = append(ss, fmt.Sprintf("%d:%d", r[0], r[1])) // enum ranges are end exclusive
			}
		}
		return start + joinStrings(ss, false) + end
	case protoreflect.EnumRanges:
		for i := 0; i < vs.Len(); i++ {
			r := vs.Get(i)
			if r[0] == r[1] {
				ss = append(ss, fmt.Sprintf("%d", r[0]))
			} else {
				ss = append(ss, fmt.Sprintf("%d:%d", r[0], int64(r[1])+1)) // enum ranges are end inclusive
			}
		}
		return start + joinStrings(ss, false) + end
	case protoreflect.FileImports:
		for i := 0; i < vs.Len(); i++ {
			var rs records
			rv := reflect.ValueOf(vs.Get(i))
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Path"), "Path"},
				{rv.MethodByName("Package"), "Package"},
				{rv.MethodByName("IsPublic"), "IsPublic"},
				{rv.MethodByName("IsWeak"), "IsWeak"},
			}...)
			ss = append(ss, "{"+rs.Join()+"}")
		}
		return start + joinStrings(ss, allowMulti) + end
	default:
		_, isEnumValue := vs.(protoreflect.EnumValueDescriptors)
		for i := 0; i < vs.Len(); i++ {
			m := reflect.ValueOf(vs).MethodByName("Get")
			v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface()
			ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue, nil))
		}
		return start + joinStrings(ss, allowMulti && isEnumValue) + end
	}
}

type methodAndName struct {
	method reflect.Value
	name   string
}

func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) {
	io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')), nil))
}

func InternalFormatDescOptForTesting(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
	return formatDescOpt(t, isRoot, allowMulti, record)
}

func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
	rv := reflect.ValueOf(t)
	rt := rv.MethodByName("ProtoType").Type().In(0)

	start, end := "{", "}"
	if isRoot {
		start = rt.Name() + "{"
	}

	_, isFile := t.(protoreflect.FileDescriptor)
	rs := records{
		allowMulti: allowMulti,
		record:     record,
	}
	if t.IsPlaceholder() {
		if isFile {
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Path"), "Path"},
				{rv.MethodByName("Package"), "Package"},
				{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
			}...)
		} else {
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("FullName"), "FullName"},
				{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
			}...)
		}
	} else {
		switch {
		case isFile:
			rs.Append(rv, methodAndName{rv.MethodByName("Syntax"), "Syntax"})
		case isRoot:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Syntax"), "Syntax"},
				{rv.MethodByName("FullName"), "FullName"},
			}...)
		default:
			rs.Append(rv, methodAndName{rv.MethodByName("Name"), "Name"})
		}
		switch t := t.(type) {
		case protoreflect.FieldDescriptor:
			accessors := []methodAndName{
				{rv.MethodByName("Number"), "Number"},
				{rv.MethodByName("Cardinality"), "Cardinality"},
				{rv.MethodByName("Kind"), "Kind"},
				{rv.MethodByName("HasJSONName"), "HasJSONName"},
				{rv.MethodByName("JSONName"), "JSONName"},
				{rv.MethodByName("HasPresence"), "HasPresence"},
				{rv.MethodByName("IsExtension"), "IsExtension"},
				{rv.MethodByName("IsPacked"), "IsPacked"},
				{rv.MethodByName("IsWeak"), "IsWeak"},
				{rv.MethodByName("IsList"), "IsList"},
				{rv.MethodByName("IsMap"), "IsMap"},
				{rv.MethodByName("MapKey"), "MapKey"},
				{rv.MethodByName("MapValue"), "MapValue"},
				{rv.MethodByName("HasDefault"), "HasDefault"},
				{rv.MethodByName("Default"), "Default"},
				{rv.MethodByName("ContainingOneof"), "ContainingOneof"},
				{rv.MethodByName("ContainingMessage"), "ContainingMessage"},
				{rv.MethodByName("Message"), "Message"},
				{rv.MethodByName("Enum"), "Enum"},
			}
			for _, s := range accessors {
				switch s.name {
				case "MapKey":
					if k := t.MapKey(); k != nil {
						rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()})
					}
				case "MapValue":
					if v := t.MapValue(); v != nil {
						switch v.Kind() {
						case protoreflect.EnumKind:
							rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Enum().FullName())})
						case protoreflect.MessageKind, protoreflect.GroupKind:
							rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Message().FullName())})
						default:
							rs.AppendRecs("MapValue", [2]string{"MapValue", v.Kind().String()})
						}
					}
				case "ContainingOneof":
					if od := t.ContainingOneof(); od != nil {
						rs.AppendRecs("ContainingOneof", [2]string{"Oneof", string(od.Name())})
					}
				case "ContainingMessage":
					if t.IsExtension() {
						rs.AppendRecs("ContainingMessage", [2]string{"Extendee", string(t.ContainingMessage().FullName())})
					}
				case "Message":
					if !t.IsMap() {
						rs.Append(rv, s)
					}
				default:
					rs.Append(rv, s)
				}
			}
		case protoreflect.OneofDescriptor:
			var ss []string
			fs := t.Fields()
			for i := 0; i < fs.Len(); i++ {
				ss = append(ss, string(fs.Get(i).Name()))
			}
			if len(ss) > 0 {
				rs.AppendRecs("Fields", [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
			}

		case protoreflect.FileDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Path"), "Path"},
				{rv.MethodByName("Package"), "Package"},
				{rv.MethodByName("Imports"), "Imports"},
				{rv.MethodByName("Messages"), "Messages"},
				{rv.MethodByName("Enums"), "Enums"},
				{rv.MethodByName("Extensions"), "Extensions"},
				{rv.MethodByName("Services"), "Services"},
			}...)

		case protoreflect.MessageDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("IsMapEntry"), "IsMapEntry"},
				{rv.MethodByName("Fields"), "Fields"},
				{rv.MethodByName("Oneofs"), "Oneofs"},
				{rv.MethodByName("ReservedNames"), "ReservedNames"},
				{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
				{rv.MethodByName("RequiredNumbers"), "RequiredNumbers"},
				{rv.MethodByName("ExtensionRanges"), "ExtensionRanges"},
				{rv.MethodByName("Messages"), "Messages"},
				{rv.MethodByName("Enums"), "Enums"},
				{rv.MethodByName("Extensions"), "Extensions"},
			}...)

		case protoreflect.EnumDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Values"), "Values"},
				{rv.MethodByName("ReservedNames"), "ReservedNames"},
				{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
				{rv.MethodByName("IsClosed"), "IsClosed"},
			}...)

		case protoreflect.EnumValueDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Number"), "Number"},
			}...)

		case protoreflect.ServiceDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Methods"), "Methods"},
			}...)

		case protoreflect.MethodDescriptor:
			rs.Append(rv, []methodAndName{
				{rv.MethodByName("Input"), "Input"},
				{rv.MethodByName("Output"), "Output"},
				{rv.MethodByName("IsStreamingClient"), "IsStreamingClient"},
				{rv.MethodByName("IsStreamingServer"), "IsStreamingServer"},
			}...)
		}
		if m := rv.MethodByName("GoType"); m.IsValid() {
			rs.Append(rv, methodAndName{m, "GoType"})
		}
	}
	return start + rs.Join() + end
}

type records struct {
	recs       [][2]string
	allowMulti bool

	// record is a function that will be called for every Append() or
	// AppendRecs() call, to be used for testing with the
	// InternalFormatDescOptForTesting function.
	record func(string)
}

func (rs *records) AppendRecs(fieldName string, newRecs [2]string) {
	if rs.record != nil {
		rs.record(fieldName)
	}
	rs.recs = append(rs.recs, newRecs)
}

func (rs *records) Append(v reflect.Value, accessors ...methodAndName) {
	for _, a := range accessors {
		if rs.record != nil {
			rs.record(a.name)
		}
		var rv reflect.Value
		if a.method.IsValid() {
			rv = a.method.Call(nil)[0]
		}
		if v.Kind() == reflect.Struct && !rv.IsValid() {
			rv = v.FieldByName(a.name)
		}
		if !rv.IsValid() {
			panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a.name))
		}
		if _, ok := rv.Interface().(protoreflect.Value); ok {
			rv = rv.MethodByName("Interface").Call(nil)[0]
			if !rv.IsNil() {
				rv = rv.Elem()
			}
		}

		// Ignore zero values.
		var isZero bool
		switch rv.Kind() {
		case reflect.Interface, reflect.Slice:
			isZero = rv.IsNil()
		case reflect.Bool:
			isZero = rv.Bool() == false
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			isZero = rv.Int() == 0
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			isZero = rv.Uint() == 0
		case reflect.String:
			isZero = rv.String() == ""
		}
		if n, ok := rv.Interface().(list); ok {
			isZero = n.Len() == 0
		}
		if isZero {
			continue
		}

		// Format the value.
		var s string
		v := rv.Interface()
		switch v := v.(type) {
		case list:
			s = formatListOpt(v, false, rs.allowMulti)
		case protoreflect.FieldDescriptor, protoreflect.OneofDescriptor, protoreflect.EnumValueDescriptor, protoreflect.MethodDescriptor:
			s = string(v.(protoreflect.Descriptor).Name())
		case protoreflect.Descriptor:
			s = string(v.FullName())
		case string:
			s = strconv.Quote(v)
		case []byte:
			s = fmt.Sprintf("%q", v)
		default:
			s = fmt.Sprint(v)
		}
		rs.recs = append(rs.recs, [2]string{a.name, s})
	}
}

func (rs *records) Join() string {
	var ss []string

	// In single line mode, simply join all records with commas.
	if !rs.allowMulti {
		for _, r := range rs.recs {
			ss = append(ss, r[0]+formatColon(0)+r[1])
		}
		return joinStrings(ss, false)
	}

	// In allowMulti line mode, align single line records for more readable output.
	var maxLen int
	flush := func(i int) {
		for _, r := range rs.recs[len(ss):i] {
			ss = append(ss, r[0]+formatColon(maxLen-len(r[0]))+r[1])
		}
		maxLen = 0
	}
	for i, r := range rs.recs {
		if isMulti := strings.Contains(r[1], "\n"); isMulti {
			flush(i)
			ss = append(ss, r[0]+formatColon(0)+strings.Join(strings.Split(r[1], "\n"), "\n\t"))
		} else if maxLen < len(r[0]) {
			maxLen = len(r[0])
		}
	}
	flush(len(rs.recs))
	return joinStrings(ss, true)
}

func formatColon(padding int) string {
	// Deliberately introduce instability into the debug output to
	// discourage users from performing string comparisons.
	// This provides us flexibility to change the output in the future.
	if detrand.Bool() {
		return ":" + strings.Repeat(" ", 1+padding) // use non-breaking spaces (U+00a0)
	} else {
		return ":" + strings.Repeat(" ", 1+padding) // use regular spaces (U+0020)
	}
}

func joinStrings(ss []string, isMulti bool) string {
	if len(ss) == 0 {
		return ""
	}
	if isMulti {
		return "\n\t" + strings.Join(ss, "\n\t") + "\n"
	}
	return strings.Join(ss, ", ")
}
