// 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 (
	"fmt"
	"sort"

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

// Modes:
//   raw: as is
//   def: merge structs, print reset as is.
//
// Possible simplifications in def mode:
//    - merge contents of multiple _literal_ structs.
//      - this is not possible if some of the elements are bulk optional
//        (or is it?).
//    - still do not ever resolve references.
//    - to do this, fields must be pre-linked to their destinations.
//    - use astutil.Sanitize to resolve shadowing and imports.
//
//
// Categories of printing:
//   - concrete
//   - optionals
//   - references
//   - constraints
//
// Mixed mode is also not supported in the old implementation (at least not
// correctly). It requires references to resolve properly, backtracking to
// a common root and prefixing that to the reference. This is now possible
// with the Environment construct and could be done later.

func (e *exporter) expr(v adt.Expr) (result ast.Expr) {
	switch x := v.(type) {
	case nil:
		return nil

	case *adt.Vertex:
		if len(x.Conjuncts) == 0 || x.IsData() {
			// Treat as literal value.
			return e.value(x)
		} // Should this be the arcs label?

		a := []conjunct{}
		for _, c := range x.Conjuncts {
			a = append(a, conjunct{c, 0})
		}

		return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...)

	case *adt.StructLit:
		c := adt.MakeRootConjunct(nil, x)
		return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c)

	case adt.Value:
		return e.value(x) // Use conjuncts.

	default:
		return e.adt(v, nil)
	}
}

// Piece out values:

// For a struct, piece out conjuncts that are already values. Those can be
// unified. All other conjuncts are added verbatim.

func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, orig ...adt.Conjunct) ast.Expr {

	e := conjuncts{
		exporter: x,
		values:   &adt.Vertex{},
		fields:   map[adt.Feature]field{},
		attrs:    []*ast.Attribute{},
	}

	_, saved := e.pushFrame(orig)
	defer e.popFrame(saved)

	for _, c := range a {
		e.top().upCount = c.up
		x := c.c.Expr()
		e.addExpr(c.c.Env, src, x, false)
	}

	if src != nil {
		for _, a := range src.Arcs {
			if x, ok := e.fields[a.Label]; ok {
				x.arc = a
				e.fields[a.Label] = x
			}
		}
	}

	s := x.top().scope

	for _, a := range e.attrs {
		s.Elts = append(s.Elts, a)
	}

	// Unify values only for one level.
	if a := e.values.Conjuncts; len(a) > 0 {
		e.values.Finalize(e.ctx)
		e.embed = append(e.embed, e.value(e.values, a...))
	}

	// Collect and order set of fields.

	fields := []adt.Feature{}
	for f := range e.fields {
		fields = append(fields, f)
	}

	// Sort fields in case features lists are missing to ensure
	// predictability. Also sort in reverse order, so that bugs
	// are more likely exposed.
	sort.Slice(fields, func(i, j int) bool {
		return fields[i] > fields[j]
	})

	m := sortArcs(extractFeatures(e.structs))
	sort.SliceStable(fields, func(i, j int) bool {
		if m[fields[j]] == 0 {
			return m[fields[i]] != 0
		}
		return m[fields[i]] > m[fields[j]]
	})

	if len(e.fields) == 0 && !e.hasEllipsis {
		switch len(e.embed) + len(e.conjuncts) {
		case 0:
			if len(e.attrs) > 0 {
				break
			}
			if len(e.structs) > 0 {
				return s
			}
			return ast.NewIdent("_")
		case 1:
			var x ast.Expr
			if len(e.conjuncts) == 1 {
				x = e.conjuncts[0]
			} else {
				x = e.embed[0]
			}
			if len(e.attrs) == 0 {
				return x
			}
			if st, ok := x.(*ast.StructLit); ok {
				s.Elts = append(s.Elts, st.Elts...)
				return s
			}
		case 2:
			if len(e.attrs) > 0 {
				break
			}
			// Simplify.
			e.conjuncts = append(e.conjuncts, e.embed...)
			return ast.NewBinExpr(token.AND, e.conjuncts...)
		}
	}

	for _, x := range e.embed {
		s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: x})
	}

	for _, f := range fields {
		field := e.fields[f]
		c := field.conjuncts

		label := e.stringLabel(f)

		if f.IsDef() {
			x.inDefinition++
		}

		a := []adt.Conjunct{}
		for _, cc := range c {
			a = append(a, cc.c)
		}

		d := &ast.Field{Label: label}

		top := e.frame(0)
		if fr, ok := top.fields[f]; ok && fr.alias != "" {
			setFieldAlias(d, fr.alias)
			fr.node = d
			top.fields[f] = fr
		}

		d.Value = e.mergeValues(f, field.arc, c, a...)

		if f.IsDef() {
			x.inDefinition--
		}

		if isOptional(a) {
			d.Optional = token.Blank.Pos()
		}
		if x.cfg.ShowDocs {
			docs := extractDocs(src, a)
			ast.SetComments(d, docs)
		}
		if x.cfg.ShowAttributes {
			for _, c := range a {
				d.Attrs = extractFieldAttrs(d.Attrs, c)
			}
		}
		s.Elts = append(s.Elts, d)
	}
	if e.hasEllipsis {
		s.Elts = append(s.Elts, &ast.Ellipsis{})
	}

	// TODO: why was this necessary?
	// else if src != nil && src.IsClosedStruct() && e.inDefinition == 0 {
	// return ast.NewCall(ast.NewIdent("close"), s)
	// }

	e.conjuncts = append(e.conjuncts, s)

	return ast.NewBinExpr(token.AND, e.conjuncts...)
}

// Conjuncts if for collecting values of a single vertex.
type conjuncts struct {
	*exporter
	// Values is used to collect non-struct values.
	values      *adt.Vertex
	embed       []ast.Expr
	conjuncts   []ast.Expr
	structs     []*adt.StructInfo
	fields      map[adt.Feature]field
	attrs       []*ast.Attribute
	hasEllipsis bool
}

func (c *conjuncts) addValueConjunct(src *adt.Vertex, env *adt.Environment, x adt.Expr) {
	switch b, ok := x.(adt.BaseValue); {
	case ok && src != nil && isTop(b) && !isTop(src.BaseValue):
		// drop top
	default:
		c.values.AddConjunct(adt.MakeRootConjunct(env, x))
	}
}

func (c *conjuncts) addConjunct(f adt.Feature, env *adt.Environment, n adt.Node) {
	x := c.fields[f]
	v := adt.MakeRootConjunct(env, n)
	x.conjuncts = append(x.conjuncts, conjunct{
		c:  v,
		up: c.top().upCount,
	})
	// x.upCounts = append(x.upCounts, c.top().upCount)
	c.fields[f] = x
}

type field struct {
	docs      []*ast.CommentGroup
	arc       *adt.Vertex
	conjuncts []conjunct
}

type conjunct struct {
	c  adt.Conjunct
	up int32
}

func (e *conjuncts) addExpr(env *adt.Environment, src *adt.Vertex, x adt.Expr, isEmbed bool) {
	switch x := x.(type) {
	case *adt.StructLit:
		e.top().upCount++

		if e.cfg.ShowAttributes {
			e.attrs = extractDeclAttrs(e.attrs, x.Src)
		}

		// Only add if it only has no bulk fields or elipsis.
		if isComplexStruct(x) {
			_, saved := e.pushFrame(nil)
			e.embed = append(e.embed, e.adt(x, nil))
			e.top().upCount-- // not necessary, but for proper form
			e.popFrame(saved)
			return
		}
		// Used for sorting.
		e.structs = append(e.structs, &adt.StructInfo{StructLit: x, Env: env})

		for _, d := range x.Decls {
			var label adt.Feature
			switch f := d.(type) {
			case *adt.Field:
				label = f.Label
			case *adt.OptionalField:
				// TODO: mark optional here.
				label = f.Label
			case *adt.Ellipsis:
				e.hasEllipsis = true
				continue
			case adt.Expr:
				e.addExpr(env, nil, f, true)
				continue

				// TODO: also handle dynamic fields
			default:
				panic(fmt.Sprintf("Unexpected type %T", d))
			}
			e.addConjunct(label, env, d)
		}
		e.top().upCount--

	case adt.Value: // other values.
		switch v := x.(type) {
		case nil:
		default:
			e.addValueConjunct(src, env, x)

		case *adt.Vertex:
			if b, ok := v.BaseValue.(*adt.Bottom); ok {
				if !b.IsIncomplete() || e.cfg.Final {
					e.addExpr(env, v, b, false)
					return
				}
			}

			switch {
			default:
				for _, c := range v.Conjuncts {
					e.addExpr(c.Env, v, c.Expr(), false)
				}

			case v.IsData():
				e.structs = append(e.structs, v.Structs...)

				if y, ok := v.BaseValue.(adt.Value); ok {
					e.addValueConjunct(src, env, y)
				}

				for _, a := range v.Arcs {
					a.Finalize(e.ctx) // TODO: should we do this?

					e.addConjunct(a.Label, env, a)
				}
			}
		}

	case *adt.BinaryExpr:
		switch {
		case x.Op == adt.AndOp && !isEmbed:
			e.addExpr(env, src, x.X, false)
			e.addExpr(env, src, x.Y, false)
		case isSelfContained(x):
			e.addValueConjunct(src, env, x)
		default:
			if isEmbed {
				e.embed = append(e.embed, e.expr(x))
			} else {
				e.conjuncts = append(e.conjuncts, e.expr(x))
			}
		}

	default:
		switch {
		case isSelfContained(x):
			e.addValueConjunct(src, env, x)
		case isEmbed:
			e.embed = append(e.embed, e.expr(x))
		default:
			e.conjuncts = append(e.conjuncts, e.expr(x))
		}
	}
}

func isTop(x adt.BaseValue) bool {
	switch v := x.(type) {
	case *adt.Top:
		return true
	case *adt.BasicType:
		return v.K == adt.TopKind
	default:
		return false
	}
}

// TODO: find a better way to annotate optionality. Maybe a special conjunct
// or store it in the field information?
func isOptional(a []adt.Conjunct) bool {
	if len(a) == 0 {
		return false
	}
	for _, c := range a {
		if v, ok := c.Expr().(*adt.Vertex); ok && !v.IsData() && len(v.Conjuncts) > 0 {
			return isOptional(v.Conjuncts)
		}
		switch f := c.Source().(type) {
		case nil:
			return false
		case *ast.Field:
			if f.Optional == token.NoPos {
				return false
			}
		}
	}
	return true
}

func isComplexStruct(s *adt.StructLit) bool {
	for _, d := range s.Decls {
		switch x := d.(type) {
		case *adt.Field:
			// TODO: remove this and also handle field annotation in expr().
			// This allows structs to be merged. Ditto below.
			if x.Src != nil {
				if _, ok := x.Src.Label.(*ast.Alias); ok {
					return ok
				}
			}

		case *adt.OptionalField:
			if x.Src != nil {
				if _, ok := x.Src.Label.(*ast.Alias); ok {
					return ok
				}
			}

		case adt.Expr:

		case *adt.Ellipsis:
			if x.Value != nil {
				return true
			}

		default:
			return true
		}
	}
	return false
}

func isSelfContained(expr adt.Expr) bool {
	switch x := expr.(type) {
	case *adt.BinaryExpr:
		return isSelfContained(x.X) && isSelfContained(x.Y)
	case *adt.UnaryExpr:
		return isSelfContained(x.X)
	case *adt.BoundExpr:
		return isSelfContained(x.Expr)
	case adt.Value:
		return true
	}
	return false
}
