// 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 export

import (
	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/core/adt"
)

// ExtractDoc collects documentation strings for a field.
//
// Comments are attached to a field with a field shorthand belong to the
// child node. So in the following the comment is attached to field bar.
//
//     // comment
//     foo: bar: 2
//
func ExtractDoc(v *adt.Vertex) (docs []*ast.CommentGroup) {
	return extractDocs(v, v.Conjuncts)
}

func extractDocs(v *adt.Vertex, a []adt.Conjunct) (docs []*ast.CommentGroup) {
	fields := []*ast.Field{}

	// Collect docs directly related to this Vertex.
	for _, x := range a {
		if v, ok := x.Expr().(*adt.Vertex); ok {
			docs = append(docs, extractDocs(v, v.Conjuncts)...)
			continue
		}
		f, ok := x.Source().(*ast.Field)
		if !ok || hasShorthandValue(f) {
			continue
		}

		fields = append(fields, f)
		for _, cg := range f.Comments() {
			if !containsDoc(docs, cg) && cg.Doc {
				docs = append(docs, cg)
			}
		}
	}

	if v == nil {
		return docs
	}

	// Collect docs from parent scopes in collapsed fields.
	for p := v.Parent; p != nil; p = p.Parent {

		newFields := []*ast.Field{}

		for _, x := range p.Conjuncts {
			f, ok := x.Source().(*ast.Field)
			if !ok || !hasShorthandValue(f) {
				continue
			}

			nested := nestedField(f)
			for _, child := range fields {
				if nested == child {
					newFields = append(newFields, f)
					for _, cg := range f.Comments() {
						if !containsDoc(docs, cg) && cg.Doc {
							docs = append(docs, cg)
						}
					}
				}
			}
		}

		fields = newFields
	}
	return docs
}

// hasShorthandValue reports whether this field has a struct value that will
// be rendered as a shorthand, for instance:
//
//     f: g: 2
//
func hasShorthandValue(f *ast.Field) bool {
	if f = nestedField(f); f == nil {
		return false
	}

	// Not a regular field, but shorthand field.
	// TODO: Should we return here? For now mimic old implementation.
	if _, _, err := ast.LabelName(f.Label); err != nil {
		return false
	}

	return true
}

// nestedField returns the child field of a field shorthand.
func nestedField(f *ast.Field) *ast.Field {
	s, _ := f.Value.(*ast.StructLit)
	if s == nil ||
		len(s.Elts) != 1 ||
		s.Lbrace != token.NoPos ||
		s.Rbrace != token.NoPos {
		return nil
	}

	f, _ = s.Elts[0].(*ast.Field)
	return f
}

func containsDoc(a []*ast.CommentGroup, cg *ast.CommentGroup) bool {
	for _, c := range a {
		if c == cg {
			return true
		}
	}

	for _, c := range a {
		if c.Text() == cg.Text() {
			return true
		}
	}

	return false
}

func ExtractFieldAttrs(v *adt.Vertex) (attrs []*ast.Attribute) {
	for _, x := range v.Conjuncts {
		attrs = extractFieldAttrs(attrs, x)
	}
	return attrs
}

func extractFieldAttrs(attrs []*ast.Attribute, c adt.Conjunct) []*ast.Attribute {
	if f, ok := c.Source().(*ast.Field); ok {
		for _, a := range f.Attrs {
			if !containsAttr(attrs, a) {
				attrs = append(attrs, a)
			}
		}
	}
	return attrs
}

func ExtractDeclAttrs(v *adt.Vertex) (attrs []*ast.Attribute) {
	for _, st := range v.Structs {
		if src := st.StructLit; src != nil {
			attrs = extractDeclAttrs(attrs, src.Src)
		}
	}
	return attrs
}

func extractDeclAttrs(attrs []*ast.Attribute, n ast.Node) []*ast.Attribute {
	switch x := n.(type) {
	case nil:
	case *ast.File:
		info := internal.GetPackageInfo(x)
		attrs = appendDeclAttrs(attrs, x.Decls[info.Index:])
	case *ast.StructLit:
		attrs = appendDeclAttrs(attrs, x.Elts)
	}
	return attrs
}

func appendDeclAttrs(a []*ast.Attribute, decls []ast.Decl) []*ast.Attribute {
	for _, d := range decls {
		if attr, ok := d.(*ast.Attribute); ok && !containsAttr(a, attr) {
			a = append(a, attr)
		}
	}
	return a
}

func containsAttr(a []*ast.Attribute, x *ast.Attribute) bool {
	for _, e := range a {
		if e.Text == x.Text {
			return true
		}
	}
	return false
}
