// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package textproto

import (
	"fmt"
	"strings"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/encoding/protobuf/pbinternal"

	"github.com/protocolbuffers/txtpbfmt/ast"
	pbast "github.com/protocolbuffers/txtpbfmt/ast"
	"github.com/protocolbuffers/txtpbfmt/parser"
)

// Encoder marshals CUE into text proto.
//
type Encoder struct {
	// Schema
}

// NewEncoder returns a new encoder, where the given options are default
// options.
func NewEncoder(options ...Option) *Encoder {
	return &Encoder{}
}

// Encode converts a CUE value to a text proto file.
//
// Fields do not need to have a @protobuf attribute except for in the following
// cases:
//
//   - it is explicitly required that only fields with an attribute are exported
//   - a struct represents a Protobuf map
//   - custom naming
//
func (e *Encoder) Encode(v cue.Value, options ...Option) ([]byte, error) {
	n := &pbast.Node{}
	enc := &encoder{}

	enc.encodeMsg(n, v)

	if enc.errs != nil {
		return nil, enc.errs
	}

	// Pretty printing does not do errors, and returns a string (why o why?).
	s := parser.Pretty(n.Children, 0)
	return []byte(s), nil
}

type encoder struct {
	errs errors.Error
}

func (e *encoder) addErr(err error) {
	e.errs = errors.Append(e.errs, errors.Promote(err, "textproto"))
}

func (e *encoder) encodeMsg(parent *pbast.Node, v cue.Value) {
	i, err := v.Fields()
	if err != nil {
		e.addErr(err)
		return
	}
	for i.Next() {
		v := i.Value()
		if !v.IsConcrete() {
			continue
		}

		info, err := pbinternal.FromIter(i)
		if err != nil {
			e.addErr(err)
		}

		switch info.CompositeType {
		case pbinternal.List:
			elems, err := v.List()
			if err != nil {
				e.addErr(err)
				return
			}
			for first := true; elems.Next(); first = false {
				n := &pbast.Node{Name: info.Name}
				if first {
					copyMeta(n, v)
				}
				elem := elems.Value()
				copyMeta(n, elem)
				parent.Children = append(parent.Children, n)
				e.encodeValue(n, elem)
			}

		case pbinternal.Map:
			i, err := v.Fields()
			if err != nil {
				e.addErr(err)
				return
			}
			for first := true; i.Next(); first = false {
				n := &pbast.Node{Name: info.Name}
				if first {
					copyMeta(n, v)
				}
				parent.Children = append(parent.Children, n)
				var key *pbast.Node
				switch info.KeyType {
				case pbinternal.String, pbinternal.Bytes:
					key = pbast.StringNode("key", i.Label())
				default:
					key = &pbast.Node{
						Name:   "key",
						Values: []*ast.Value{{Value: i.Label()}},
					}
				}
				n.Children = append(n.Children, key)

				value := &pbast.Node{Name: "value"}
				e.encodeValue(value, i.Value())
				n.Children = append(n.Children, value)
			}

		default:
			n := &pbast.Node{Name: info.Name}
			copyMeta(n, v)
			e.encodeValue(n, v)
			// Don't add if there are no values or children.
			parent.Children = append(parent.Children, n)
		}
	}
}

// copyMeta copies metadata from nodes to values.
//
// TODO: also copy positions. The textproto API is rather messy and complex,
// though, and so far it seems to be quite buggy too. Not sure if it is worth
// the effort.
func copyMeta(x *pbast.Node, v cue.Value) {
	for _, doc := range v.Doc() {
		s := strings.TrimRight(doc.Text(), "\n")
		for _, c := range strings.Split(s, "\n") {
			x.PreComments = append(x.PreComments, "# "+c)
		}
	}
}

func (e *encoder) encodeValue(n *pbast.Node, v cue.Value) {
	var value string
	switch v.Kind() {
	case cue.StructKind:
		e.encodeMsg(n, v)

	case cue.StringKind:
		s, err := v.String()
		if err != nil {
			e.addErr(err)
		}
		sn := pbast.StringNode("foo", s)
		n.Values = append(n.Values, sn.Values...)

	case cue.BytesKind:
		b, err := v.Bytes()
		if err != nil {
			e.addErr(err)
		}
		sn := pbast.StringNode("foo", string(b))
		n.Values = append(n.Values, sn.Values...)

	case cue.BoolKind:
		value = fmt.Sprint(v)
		n.Values = append(n.Values, &pbast.Value{Value: value})

	case cue.IntKind, cue.FloatKind, cue.NumberKind:
		d, _ := v.Decimal()
		value := d.String()

		if info, _ := pbinternal.FromValue("", v); !info.IsEnum {
		} else if i, err := v.Int64(); err != nil {
		} else if s := pbinternal.MatchByInt(v, i); s != "" {
			value = s
		}

		n.Values = append(n.Values, &pbast.Value{Value: value})

	default:
		e.addErr(errors.Newf(v.Pos(), "textproto: unknown type %v", v.Kind()))
	}
}
