// Copyright 2020 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 yaml

import (
	"bytes"
	"math/big"
	"strings"

	"gopkg.in/yaml.v3"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/literal"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal/astinternal"
)

// Encode converts a CUE AST to YAML.
//
// The given file must only contain values that can be directly supported by
// YAML:
//    Type          Restrictions
//    BasicLit
//    File          no imports, aliases, or definitions
//    StructLit     no embeddings, aliases, or definitions
//    List
//    Field         must be regular; label must be a BasicLit or Ident
//    CommentGroup
//
//    TODO: support anchors through Ident.
func Encode(n ast.Node) (b []byte, err error) {
	y, err := encode(n)
	if err != nil {
		return nil, err
	}
	w := &bytes.Buffer{}
	enc := yaml.NewEncoder(w)
	// Use idiomatic indentation.
	enc.SetIndent(2)
	if err = enc.Encode(y); err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func encode(n ast.Node) (y *yaml.Node, err error) {
	switch x := n.(type) {
	case *ast.BasicLit:
		y, err = encodeScalar(x)

	case *ast.ListLit:
		y, err = encodeExprs(x.Elts)
		line := x.Lbrack.Line()
		if err == nil && line > 0 && line == x.Rbrack.Line() {
			y.Style = yaml.FlowStyle
		}

	case *ast.StructLit:
		y, err = encodeDecls(x.Elts)
		line := x.Lbrace.Line()
		if err == nil && line > 0 && line == x.Rbrace.Line() {
			y.Style = yaml.FlowStyle
		}

	case *ast.File:
		y, err = encodeDecls(x.Decls)

	case *ast.UnaryExpr:
		b, ok := x.X.(*ast.BasicLit)
		if ok && x.Op == token.SUB && (b.Kind == token.INT || b.Kind == token.FLOAT) {
			y, err = encodeScalar(b)
			if !strings.HasPrefix(y.Value, "-") {
				y.Value = "-" + y.Value
				break
			}
		}
		return nil, errors.Newf(x.Pos(), "yaml: unsupported node %s (%T)", astinternal.DebugStr(x), x)
	default:
		return nil, errors.Newf(x.Pos(), "yaml: unsupported node %s (%T)", astinternal.DebugStr(x), x)
	}
	if err != nil {
		return nil, err
	}
	addDocs(n, y, y)
	return y, nil
}

func encodeScalar(b *ast.BasicLit) (n *yaml.Node, err error) {
	n = &yaml.Node{Kind: yaml.ScalarNode}

	switch b.Kind {
	case token.INT:
		var x big.Int
		if err := setNum(n, b.Value, &x); err != nil {
			return nil, err
		}

	case token.FLOAT:
		var x big.Float
		if err := setNum(n, b.Value, &x); err != nil {
			return nil, err
		}

	case token.TRUE, token.FALSE, token.NULL:
		n.Value = b.Value

	case token.STRING:
		str, err := literal.Unquote(b.Value)
		if err != nil {
			return nil, err
		}
		n.SetString(str)

	default:
		return nil, errors.Newf(b.Pos(), "unknown literal type %v", b.Kind)
	}
	return n, nil
}

func setNum(n *yaml.Node, s string, x interface{}) error {
	if yaml.Unmarshal([]byte(s), x) == nil {
		n.Value = s
		return nil
	}

	var ni literal.NumInfo
	if err := literal.ParseNum(s, &ni); err != nil {
		return err
	}
	n.Value = ni.String()
	return nil
}

func encodeExprs(exprs []ast.Expr) (n *yaml.Node, err error) {
	n = &yaml.Node{Kind: yaml.SequenceNode}

	for _, elem := range exprs {
		e, err := encode(elem)
		if err != nil {
			return nil, err
		}
		n.Content = append(n.Content, e)
	}
	return n, nil
}

// encodeDecls converts a sequence of declarations to a value. If it encounters
// an embedded value, it will return this expression. This is more relaxed for
// structs than is currently allowed for CUE, but the expectation is that this
// will be allowed at some point. The input would still be illegal CUE.
func encodeDecls(decls []ast.Decl) (n *yaml.Node, err error) {
	n = &yaml.Node{Kind: yaml.MappingNode}

	docForNext := strings.Builder{}
	var lastHead, lastFoot *yaml.Node
	hasEmbed := false
	for _, d := range decls {
		switch x := d.(type) {
		default:
			return nil, errors.Newf(x.Pos(), "yaml: unsupported node %s (%T)", astinternal.DebugStr(x), x)

		case *ast.Package:
			if len(n.Content) > 0 {
				return nil, errors.Newf(x.Pos(), "invalid package clause")
			}
			continue

		case *ast.CommentGroup:
			docForNext.WriteString(docToYAML(x))
			docForNext.WriteString("\n\n")
			continue

		case *ast.Attribute:
			continue

		case *ast.Field:
			if x.Token == token.ISA {
				return nil, errors.Newf(x.TokenPos, "yaml: definition not allowed")
			}
			if x.Optional != token.NoPos {
				return nil, errors.Newf(x.Optional, "yaml: optional fields not allowed")
			}
			if hasEmbed {
				return nil, errors.Newf(x.TokenPos, "yaml: embedding mixed with fields")
			}
			name, _, err := ast.LabelName(x.Label)
			if err != nil {
				return nil, errors.Newf(x.Label.Pos(), "yaml: only literal labels allowed")
			}

			label := &yaml.Node{}
			addDocs(x.Label, label, label)
			label.SetString(name)

			value, err := encode(x.Value)
			if err != nil {
				return nil, err
			}
			lastHead = label
			lastFoot = value
			addDocs(x, label, value)
			n.Content = append(n.Content, label)
			n.Content = append(n.Content, value)

		case *ast.EmbedDecl:
			if hasEmbed {
				return nil, errors.Newf(x.Pos(), "yaml: multiple embedded values")
			}
			hasEmbed = true
			e, err := encode(x.Expr)
			if err != nil {
				return nil, err
			}
			addDocs(x, e, e)
			lastHead = e
			lastFoot = e
			n.Content = append(n.Content, e)
		}
		if docForNext.Len() > 0 {
			docForNext.WriteString(lastHead.HeadComment)
			lastHead.HeadComment = docForNext.String()
			docForNext.Reset()
		}
	}

	if docForNext.Len() > 0 && lastFoot != nil {
		if !strings.HasSuffix(lastFoot.FootComment, "\n") {
			lastFoot.FootComment += "\n"
		}
		n := docForNext.Len()
		lastFoot.FootComment += docForNext.String()[:n-1]
	}

	if hasEmbed {
		return n.Content[0], nil
	}

	return n, nil
}

// addDocs prefixes head, replaces line and appends foot comments.
func addDocs(n ast.Node, h, f *yaml.Node) {
	head := ""
	isDoc := false
	for _, c := range ast.Comments(n) {
		switch {
		case c.Line:
			f.LineComment = docToYAML(c)

		case c.Position > 0:
			if f.FootComment != "" {
				f.FootComment += "\n\n"
			} else if relPos := c.Pos().RelPos(); relPos == token.NewSection {
				f.FootComment += "\n"
			}
			f.FootComment += docToYAML(c)

		default:
			if head != "" {
				head += "\n\n"
			}
			head += docToYAML(c)
			isDoc = isDoc || c.Doc
		}
	}

	if head != "" {
		if h.HeadComment != "" || !isDoc {
			head += "\n\n"
		}
		h.HeadComment = head + h.HeadComment
	}
}

// docToYAML converts a CUE CommentGroup to a YAML comment string. This ensures
// that comments with empty lines get properly converted.
func docToYAML(c *ast.CommentGroup) string {
	s := c.Text()
	if strings.HasSuffix(s, "\n") { // always true
		s = s[:len(s)-1]
	}
	lines := strings.Split(s, "\n")
	for i, l := range lines {
		if l == "" {
			lines[i] = "#"
		} else {
			lines[i] = "# " + l
		}
	}
	return strings.Join(lines, "\n")
}
