// 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/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/literal"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/encoding/protobuf/pbinternal"
	"cuelang.org/go/internal/core/adt"
	"cuelang.org/go/internal/value"

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

// Option defines options for the decoder.
// There are currently no options.
type Option func(*options)

type options struct {
}

// NewDecoder returns a new Decoder
func NewDecoder(option ...Option) *Decoder {
	d := &Decoder{}
	_ = d.m // work around linter bug.
	return d
}

// A Decoder caches conversions of cue.Value between calls to its methods.
type Decoder struct {
	m map[*adt.Vertex]*mapping
}

type decoder struct {
	*Decoder

	// Reset on each call
	errs errors.Error
	file *token.File
}

// Parse parses the given textproto bytes and converts them to a CUE expression,
// using schema as the guideline for conversion using the following rules:
//
//    - the @protobuf attribute is optional, but is necessary for:
//        - interpreting protobuf maps
//        - using a name different from the CUE name
//    - fields in the textproto that have no corresponding field in
//      schema are ignored
//
// NOTE: the filename is used for associating position information. However,
// currently no position information is associated with the text proto because
// the position information of github.com/protocolbuffers/txtpbfmt is too
// unreliable to be useful.
func (d *Decoder) Parse(schema cue.Value, filename string, b []byte) (ast.Expr, error) {
	dec := decoder{Decoder: d}

	// dec.errs = nil

	f := token.NewFile(filename, 0, len(b))
	f.SetLinesForContent(b)
	dec.file = f

	cfg := parser.Config{}
	nodes, err := parser.ParseWithConfig(b, cfg)
	if err != nil {
		return nil, errors.Newf(token.NoPos, "textproto: %v", err)
	}

	m := dec.parseSchema(schema)
	if dec.errs != nil {
		return nil, dec.errs
	}

	n := dec.decodeMsg(m, nodes)
	if dec.errs != nil {
		return nil, dec.errs
	}

	return n, nil
}

// Don't expose until the protobuf APIs settle down.
// func (d *decoder) Decode(schema cue.Value, textpbfmt) (cue.Value, error) {
// }

type mapping struct {
	children map[string]*fieldInfo
}

type fieldInfo struct {
	pbinternal.Info
	msg *mapping
	// keytype, for now
}

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

func (d *decoder) addErrf(pos pbast.Position, format string, args ...interface{}) {
	err := errors.Newf(d.protoPos(pos), "textproto: "+format, args...)
	d.errs = errors.Append(d.errs, err)
}

func (d *decoder) protoPos(p pbast.Position) token.Pos {
	return d.file.Pos(int(p.Byte), token.NoRelPos)
}

// parseSchema walks over a CUE "type", converts it to an internal data
// structure that is used for parsing text proto, and writes it to
//
func (d *decoder) parseSchema(schema cue.Value) *mapping {
	_, v := value.ToInternal(schema)
	if v == nil {
		return nil
	}

	if d.m == nil {
		d.m = map[*adt.Vertex]*mapping{}
	} else if m := d.m[v]; m != nil {
		return m
	}

	m := &mapping{children: map[string]*fieldInfo{}}

	i, err := schema.Fields()
	if err != nil {
		d.addErr(err)
		return nil
	}

	for i.Next() {
		info, err := pbinternal.FromIter(i)
		if err != nil {
			d.addErr(err)
			continue
		}

		var msg *mapping

		switch info.CompositeType {
		case pbinternal.Normal:
			switch info.ValueType {
			case pbinternal.Message:
				msg = d.parseSchema(i.Value())
			}

		case pbinternal.List, pbinternal.Map:
			e, _ := i.Value().Elem()
			if e.IncompleteKind() == cue.StructKind {
				msg = d.parseSchema(e)
			}
		}

		m.children[info.Name] = &fieldInfo{
			Info: info,
			msg:  msg,
		}
	}

	d.m[v] = m
	return m
}

func (d *decoder) decodeMsg(m *mapping, n []*pbast.Node) ast.Expr {
	st := &ast.StructLit{}

	var listMap map[string]*ast.ListLit

	for _, x := range n {
		if x.Values == nil && x.Children == nil {
			if cg := addComments(x.PreComments...); cg != nil {
				ast.SetRelPos(cg, token.NewSection)
				st.Elts = append(st.Elts, cg)
				continue
			}
		}
		if m == nil {
			continue
		}
		f, ok := m.children[x.Name]
		if !ok {
			continue // ignore unknown fields
		}

		var value ast.Expr

		switch f.CompositeType {
		default:
			value = d.decodeValue(f, x)

		case pbinternal.List:
			if listMap == nil {
				listMap = make(map[string]*ast.ListLit)
			}

			list := listMap[f.CUEName]
			if list == nil {
				list = &ast.ListLit{}
				listMap[f.CUEName] = list
				value = list
			}

			if len(x.Values) == 1 || f.ValueType == pbinternal.Message {
				v := d.decodeValue(f, x)
				if value == nil {
					if cg := addComments(x.PreComments...); cg != nil {
						cg.Doc = true
						ast.AddComment(v, cg)
					}
				}
				if cg := addComments(x.PostValuesComments...); cg != nil {
					cg.Position = 4
					ast.AddComment(v, cg)
				}
				list.Elts = append(list.Elts, v)
				break
			}

			var last ast.Expr
			// Handle [1, 2, 3]
			for _, v := range x.Values {
				if v.Value == "" {
					if cg := addComments(v.PreComments...); cg != nil {
						if last != nil {
							cg.Position = 4
							ast.AddComment(last, cg)
						} else {
							cg.Position = 1
							ast.AddComment(list, cg)
						}
					}
					continue
				}
				y := *x
				y.Values = []*pbast.Value{v}
				last = d.decodeValue(f, &y)
				list.Elts = append(list.Elts, last)
			}
			if cg := addComments(x.PostValuesComments...); cg != nil {
				if last != nil {
					cg.Position = 4
					ast.AddComment(last, cg)
				} else {
					cg.Position = 1
					ast.AddComment(list, cg)
				}
			}
			if cg := addComments(x.ClosingBraceComment); cg != nil {
				cg.Position = 4
				ast.AddComment(list, cg)
			}

		case pbinternal.Map:
			// mapValue: {
			//     key: 123
			//     value: "string"
			// }
			if k := len(x.Values); k > 0 {
				d.addErrf(x.Start, "values not allowed for Message type; found %d", k)
			}

			var (
				key ast.Label
				val ast.Expr
			)

			for _, c := range x.Children {
				if len(c.Values) != 1 {
					d.addErrf(x.Start, "expected 1 value, found %d", len(c.Values))
					continue
				}
				s := c.Values[0].Value

				switch c.Name {
				case "key":
					if strings.HasPrefix(s, `"`) {
						key = &ast.BasicLit{Kind: token.STRING, Value: s}
					} else {
						key = ast.NewString(s)
					}

				case "value":
					val = d.decodeValue(f, c)

					if cg := addComments(x.ClosingBraceComment); cg != nil {
						cg.Line = true
						ast.AddComment(val, cg)
					}

				default:
					d.addErrf(c.Start, "unsupported key name %q in map", c.Name)
					continue
				}
			}

			if key != nil && val != nil {
				value = ast.NewStruct(key, val)
			}
		}

		if value != nil {
			var label ast.Label
			if s := f.CUEName; ast.IsValidIdent(s) {
				label = ast.NewIdent(s)
			} else {
				label = ast.NewString(s)

			}
			// TODO: convert line number information. However, position
			// information in textpbfmt packages is too wonky to be useful
			f := &ast.Field{
				Label: label,
				Value: value,
				// Attrs: []*ast.Attribute{{Text: f.attr.}},
			}
			if cg := addComments(x.PreComments...); cg != nil {
				cg.Doc = true
				ast.AddComment(f, cg)
			}
			st.Elts = append(st.Elts, f)
		}
	}

	return st
}

func addComments(lines ...string) (cg *ast.CommentGroup) {
	var a []*ast.Comment
	for _, c := range lines {
		if !strings.HasPrefix(c, "#") {
			continue
		}
		a = append(a, &ast.Comment{Text: "//" + c[1:]})
	}
	if a != nil {
		cg = &ast.CommentGroup{List: a}
	}
	return cg
}

func (d *decoder) decodeValue(f *fieldInfo, n *pbast.Node) (x ast.Expr) {
	if f.ValueType == pbinternal.Message {
		if k := len(n.Values); k > 0 {
			d.addErrf(n.Start, "values not allowed for Message type; found %d", k)
		}
		x = d.decodeMsg(f.msg, n.Children)
		if cg := addComments(n.ClosingBraceComment); cg != nil {
			cg.Line = true
			cg.Position = 4
			ast.AddComment(x, cg)
		}
		return x
	}

	if len(n.Values) != 1 {
		d.addErrf(n.Start, "expected 1 value, found %d", len(n.Values))
		return nil
	}
	v := n.Values[0]

	defer func() {
		if cg := addComments(v.PreComments...); cg != nil {
			cg.Doc = true
			ast.AddComment(x, cg)
		}
		if cg := addComments(v.InlineComment); cg != nil {
			cg.Line = true
			cg.Position = 2
			ast.AddComment(x, cg)
		}
	}()

	switch f.ValueType {
	case pbinternal.String, pbinternal.Bytes:
		s, err := unquote.Unquote(n)
		if err != nil {
			d.addErrf(n.Start, "invalid string or bytes: %v", err)
		}
		if f.ValueType == pbinternal.String {
			s = literal.String.Quote(s)
		} else {
			s = literal.Bytes.Quote(s)
		}
		return &ast.BasicLit{Kind: token.STRING, Value: s}

	case pbinternal.Bool:
		switch v.Value {
		case "true":
			return ast.NewBool(true)

		case "false":
		default:
			d.addErrf(n.Start, "invalid bool %s", v.Value)
		}
		return ast.NewBool(false)

	case pbinternal.Int, pbinternal.Float:
		s := v.Value
		switch s {
		case "inf", "nan":
			// TODO: include message.
			return &ast.BottomLit{}
		}

		var info literal.NumInfo
		if err := literal.ParseNum(s, &info); err != nil {
			var x ast.BasicLit
			if pbinternal.MatchBySymbol(f.Value, s, &x) {
				return &x
			}
			d.addErrf(n.Start, "invalid number %s", s)
		}
		if !info.IsInt() {
			return &ast.BasicLit{Kind: token.FLOAT, Value: s}
		}
		return &ast.BasicLit{Kind: token.INT, Value: info.String()}

	default:
		panic(fmt.Sprintf("unexpected type %v", f.ValueType))
	}
}
