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

// walk provides functions for visiting the nodes of an ADT tree.
package walk

import (
	"fmt"

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

// Features calls f for all features used in x and indicates whether the
// feature is used as a reference or not.
func Features(x adt.Expr, f func(label adt.Feature, src adt.Node)) {
	w := Visitor{
		Feature: f,
	}
	w.Expr(x)
}

type Visitor struct {
	// TODO: lets really should be special fields
	letDone map[adt.Expr]bool

	Feature func(f adt.Feature, src adt.Node)
	Before  func(adt.Node) bool
}

func (w *Visitor) init() {
	if w.letDone == nil {
		w.letDone = map[adt.Expr]bool{}
	}
}

func (w *Visitor) Expr(x adt.Expr) {
	w.init()
	w.node(x)
}

func (w *Visitor) feature(x adt.Feature, src adt.Node) {
	if w.Feature != nil {
		w.Feature(x, src)
	}
}

func (w *Visitor) node(n adt.Node) {
	if w.Before != nil && !w.Before(n) {
		return
	}

	switch x := n.(type) {
	case nil:

	// TODO: special-case Vertex?
	case adt.Value:

	case *adt.ListLit:
		for _, x := range x.Elems {
			w.node(x)
		}

	case *adt.StructLit:
		for _, x := range x.Decls {
			w.node(x)
		}

	case *adt.FieldReference:
		w.feature(x.Label, x)

	case *adt.LabelReference:

	case *adt.DynamicReference:

	case *adt.ImportReference:
		w.feature(x.ImportPath, x)
		w.feature(x.Label, x)

	case *adt.LetReference:
		w.feature(x.Label, x)
		if w.letDone == nil {
			w.letDone = map[adt.Expr]bool{}
		}
		if !w.letDone[x.X] {
			w.letDone[x.X] = true
			w.node(x.X)
		}

	case *adt.SelectorExpr:
		w.node(x.X)
		w.feature(x.Sel, x)

	case *adt.IndexExpr:
		w.node(x.X)
		w.node(x.Index)

	case *adt.SliceExpr:
		w.node(x.X)
		w.node(x.Lo)
		w.node(x.Hi)
		w.node(x.Stride)

	case *adt.Interpolation:
		for _, x := range x.Parts {
			w.node(x)
		}

	case *adt.BoundExpr:
		w.node(x.Expr)

	case *adt.UnaryExpr:
		w.node(x.X)

	case *adt.BinaryExpr:
		w.node(x.X)
		w.node(x.Y)

	case *adt.CallExpr:
		w.node(x.Fun)
		for _, arg := range x.Args {
			w.node(arg)
		}

	case *adt.DisjunctionExpr:
		for _, d := range x.Values {
			w.node(d.Val)
		}

	// Fields

	case *adt.Ellipsis:
		if x.Value != nil {
			w.node(x.Value)
		}

	case *adt.Field:
		w.feature(x.Label, x)
		w.node(x.Value)

	case *adt.OptionalField:
		w.feature(x.Label, x)
		w.node(x.Value)

	case *adt.BulkOptionalField:
		w.node(x.Filter)
		w.node(x.Value)

	case *adt.DynamicField:
		w.node(x.Key)
		w.node(x.Value)

	// Yielders

	case *adt.ForClause:
		w.feature(x.Key, x)
		w.feature(x.Value, x)
		w.node(x.Dst)

	case *adt.IfClause:
		w.node(x.Condition)
		w.node(x.Dst)

	case *adt.LetClause:
		w.feature(x.Label, x)
		w.node(x.Expr)
		w.node(x.Dst)

	case *adt.ValueClause:
		w.node(x.StructLit)

	default:
		panic(fmt.Sprintf("unknown field %T", x))
	}
}
