// 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 dep analyzes dependencies between values.
package dep

import (
	"errors"

	"cuelang.org/go/internal/core/adt"
)

// A Dependency is a reference and the node that reference resolves to.
type Dependency struct {
	// Node is the referenced node.
	Node *adt.Vertex

	// Reference is the expression that referenced the node.
	Reference adt.Resolver

	top bool
}

// Import returns the import reference or nil if the reference was within
// the same package as the visited Vertex.
func (d *Dependency) Import() *adt.ImportReference {
	x, _ := d.Reference.(adt.Expr)
	return importRef(x)
}

// IsRoot reports whether the dependency is referenced by the root of the
// original Vertex passed to any of the Visit* functions, and not one of its
// descendent arcs. This always returns true for Visit().
func (d *Dependency) IsRoot() bool {
	return d.top
}

func (d *Dependency) Path() []adt.Feature {
	return nil
}

func importRef(r adt.Expr) *adt.ImportReference {
	switch x := r.(type) {
	case *adt.ImportReference:
		return x
	case *adt.SelectorExpr:
		return importRef(x.X)
	case *adt.IndexExpr:
		return importRef(x.X)
	}
	return nil
}

// VisitFunc is used for reporting dependencies.
type VisitFunc func(Dependency) error

// Visit calls f for all vertices referenced by the conjuncts of n without
// descending into the elements of list or fields of structs. Only references
// that do not refer to the conjuncts of n itself are reported.
func Visit(c *adt.OpContext, n *adt.Vertex, f VisitFunc) error {
	return visit(c, n, f, false, true)
}

// VisitAll calls f for all vertices referenced by the conjuncts of n including
// those of descendant fields and elements. Only references that do not refer to
// the conjuncts of n itself are reported.
func VisitAll(c *adt.OpContext, n *adt.Vertex, f VisitFunc) error {
	return visit(c, n, f, true, true)
}

// VisitFields calls f for n and all its descendent arcs that have a conjunct
// that originates from a conjunct in n. Only the conjuncts of n that ended up
// as a conjunct in an actual field are visited and they are visited for each
// field in which the occurs.
func VisitFields(c *adt.OpContext, n *adt.Vertex, f VisitFunc) error {
	m := marked{}

	m.markExpr(n)

	dynamic(c, n, f, m, true)
	return nil
}

var empty *adt.Vertex

func init() {
	empty = &adt.Vertex{}
	empty.UpdateStatus(adt.Finalized)
}

func visit(c *adt.OpContext, n *adt.Vertex, f VisitFunc, all, top bool) (err error) {
	if c == nil {
		panic("nil context")
	}
	v := visitor{
		ctxt:  c,
		visit: f,
		node:  n,
		all:   all,
		top:   top,
	}

	defer func() {
		switch x := recover(); x {
		case nil:
		case aborted:
			err = v.err
		default:
			panic(x)
		}
	}()

	for _, x := range n.Conjuncts {
		v.markExpr(x.Env, x.Expr())
	}

	return nil
}

var aborted = errors.New("aborted")

type visitor struct {
	ctxt  *adt.OpContext
	visit VisitFunc
	node  *adt.Vertex
	err   error
	all   bool
	top   bool
}

// TODO: factor out the below logic as either a low-level dependency analyzer or
// some walk functionality.

// markExpr visits all nodes in an expression to mark dependencies.
func (c *visitor) markExpr(env *adt.Environment, expr adt.Expr) {
	switch x := expr.(type) {
	case nil:
	case adt.Resolver:
		c.markResolver(env, x)

	case *adt.BinaryExpr:
		c.markExpr(env, x.X)
		c.markExpr(env, x.Y)

	case *adt.UnaryExpr:
		c.markExpr(env, x.X)

	case *adt.Interpolation:
		for i := 1; i < len(x.Parts); i += 2 {
			c.markExpr(env, x.Parts[i])
		}

	case *adt.BoundExpr:
		c.markExpr(env, x.Expr)

	case *adt.CallExpr:
		c.markExpr(env, x.Fun)
		saved := c.all
		c.all = true
		for _, a := range x.Args {
			c.markExpr(env, a)
		}
		c.all = saved

	case *adt.DisjunctionExpr:
		for _, d := range x.Values {
			c.markExpr(env, d.Val)
		}

	case *adt.SliceExpr:
		c.markExpr(env, x.X)
		c.markExpr(env, x.Lo)
		c.markExpr(env, x.Hi)
		c.markExpr(env, x.Stride)

	case *adt.ListLit:
		for _, e := range x.Elems {
			switch x := e.(type) {
			case adt.Yielder:
				c.markYielder(env, x)

			case adt.Expr:
				c.markSubExpr(env, x)

			case *adt.Ellipsis:
				if x.Value != nil {
					c.markSubExpr(env, x.Value)
				}
			}
		}

	case *adt.StructLit:
		env := &adt.Environment{Up: env, Vertex: empty}
		for _, e := range x.Decls {
			c.markDecl(env, e)
		}
	}
}

// markResolve resolves dependencies.
func (c *visitor) markResolver(env *adt.Environment, r adt.Resolver) {
	switch x := r.(type) {
	case nil:
	case *adt.LetReference:
		saved := c.ctxt.PushState(env, nil)
		env := c.ctxt.Env(x.UpCount)
		c.markExpr(env, x.X)
		c.ctxt.PopState(saved)
		return
	}

	if ref, _ := c.ctxt.Resolve(env, r); ref != nil {
		if ref != c.node {
			d := Dependency{
				Node:      ref,
				Reference: r,
				top:       c.top,
			}
			if err := c.visit(d); err != nil {
				c.err = err
				panic(aborted)
			}
		}

		return
	}

	// It is possible that a reference cannot be resolved because it is
	// incomplete. In this case, we should check whether subexpressions of the
	// reference can be resolved to mark those dependencies. For instance,
	// prefix paths of selectors and the value or index of an index experssion
	// may independently resolve to a valid dependency.

	switch x := r.(type) {
	case *adt.NodeLink:
		panic("unreachable")

	case *adt.IndexExpr:
		c.markExpr(env, x.X)
		c.markExpr(env, x.Index)

	case *adt.SelectorExpr:
		c.markExpr(env, x.X)
	}
}

func (c *visitor) markSubExpr(env *adt.Environment, x adt.Expr) {
	if c.all {
		saved := c.top
		c.top = false
		c.markExpr(env, x)
		c.top = saved
	}
}

func (c *visitor) markDecl(env *adt.Environment, d adt.Decl) {
	switch x := d.(type) {
	case *adt.Field:
		c.markSubExpr(env, x.Value)

	case *adt.OptionalField:
		// when dynamic, only continue if there is evidence of
		// the field in the parallel actual evaluation.
		c.markSubExpr(env, x.Value)

	case *adt.BulkOptionalField:
		c.markExpr(env, x.Filter)
		// when dynamic, only continue if there is evidence of
		// the field in the parallel actual evaluation.
		c.markSubExpr(env, x.Value)

	case *adt.DynamicField:
		c.markExpr(env, x.Key)
		// when dynamic, only continue if there is evidence of
		// a matching field in the parallel actual evaluation.
		c.markSubExpr(env, x.Value)

	case adt.Yielder:
		c.markYielder(env, x)

	case adt.Expr:
		c.markExpr(env, x)

	case *adt.Ellipsis:
		if x.Value != nil {
			c.markSubExpr(env, x.Value)
		}
	}
}

func (c *visitor) markYielder(env *adt.Environment, y adt.Yielder) {
	switch x := y.(type) {
	case *adt.ForClause:
		c.markExpr(env, x.Src)
		env := &adt.Environment{Up: env, Vertex: empty}
		c.markYielder(env, x.Dst)
		// In dynamic mode, iterate over all actual value and
		// evaluate.

	case *adt.LetClause:
		c.markExpr(env, x.Expr)
		env := &adt.Environment{Up: env, Vertex: empty}
		c.markYielder(env, x.Dst)

	case *adt.IfClause:
		c.markExpr(env, x.Condition)
		// In dynamic mode, only continue if condition is true.
		c.markYielder(env, x.Dst)

	case *adt.ValueClause:
		c.markExpr(env, x.StructLit)
	}
}
