/*
Copyright 2020 Google LLC

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

    https://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 bzlenv provides function to create and update a static environment.
package bzlenv

import (
	"github.com/bazelbuild/buildtools/build"
)

// ValueKind describes how a binding was declared.
type ValueKind int

// List of ValueKind values.
const (
	Builtin   ValueKind = iota // language builtin
	Imported                   // declared with load()
	Global                     // declared with assignment on top-level
	Function                   // declared with a def
	Parameter                  // function parameter
	Local                      // local variable, defined with assignment or as a loop variable
)

func (k ValueKind) String() string {
	switch k {
	case Builtin:
		return "builtin"
	case Imported:
		return "imported"
	case Global:
		return "global"
	case Function:
		return "function"
	case Parameter:
		return "parameter"
	case Local:
		return "local"
	default:
		panic(k)
	}
}

// NameInfo represents information about a symbol name.
type NameInfo struct {
	ID         int    // unique identifier
	Name       string // name of the variable (not unique)
	Kind       ValueKind
	Definition build.Expr // node that defines the value
}

type block map[string]NameInfo

// Environment represents a static environment (e.g. information about all available symbols).
type Environment struct {
	Blocks   []block
	Function *build.DefStmt // enclosing function (or nil on top-level)
	nextID   int            // used to create unique identifiers
	Stack    []build.Expr   // parents of the current node
}

// NewEnvironment creates a new empty Environment.
func NewEnvironment() *Environment {
	sc := block{}
	return &Environment{[]block{sc}, nil, 0, []build.Expr{}}
}

func (e *Environment) enterBlock() {
	e.Blocks = append(e.Blocks, block{})
}

func (e *Environment) exitBlock() {
	if len(e.Blocks) < 1 {
		panic("no block to close")
	}
	e.Blocks = e.Blocks[:len(e.Blocks)-1]
}

func (e *Environment) currentBlock() block {
	return e.Blocks[len(e.Blocks)-1]
}

func (sc *block) declare(name string, kind ValueKind, definition build.Expr, id int) {
	(*sc)[name] = NameInfo{
		ID:         id,
		Name:       name,
		Definition: definition,
		Kind:       kind}
}

// Get resolves the name and resolves information about the binding (or nil if it's not defined).
func (e *Environment) Get(name string) *NameInfo {
	for i := len(e.Blocks) - 1; i >= 0; i-- {
		if ret, ok := e.Blocks[i][name]; ok {
			return &ret
		}
	}
	return nil
}

func (e *Environment) declare(name string, kind ValueKind, node build.Expr) {
	sc := e.currentBlock()
	sc.declare(name, kind, node, e.nextID)
	e.nextID++
}

func declareGlobals(stmts []build.Expr, env *Environment) {
	for _, node := range stmts {
		switch node := node.(type) {
		case *build.LoadStmt:
			for _, ident := range node.To {
				env.declare(ident.Name, Imported, ident)
			}
		case *build.AssignExpr:
			kind := Local
			if env.Function == nil {
				kind = Global
			}
			for _, id := range CollectLValues(node.LHS) {
				env.declare(id.Name, kind, node)
			}
		case *build.DefStmt:
			env.declare(node.Name, Function, node)
		}
	}
}

// CollectLValues returns the list of identifiers that are assigned (assuming that node is a valid
// LValue). For example, it returns `a`, `b` and `c` for the input `a, (b, c)`.
func CollectLValues(node build.Expr) []*build.Ident {
	var result []*build.Ident
	switch node := node.(type) {
	case *build.Ident:
		result = append(result, node)
	case *build.TupleExpr:
		for _, item := range node.List {
			result = append(result, CollectLValues(item)...)
		}
	case *build.ListExpr:
		for _, item := range node.List {
			result = append(result, CollectLValues(item)...)
		}
	}
	return result
}

func declareParams(fct *build.DefStmt, env *Environment) {
	for _, node := range fct.Params {
		name, _ := build.GetParamName(node)
		env.declare(name, Parameter, node)
	}
}

func declareLocalVariables(stmts []build.Expr, env *Environment) {
	for _, stmt := range stmts {
		switch node := stmt.(type) {
		case *build.AssignExpr:
			kind := Local
			if env.Function == nil {
				kind = Global
			}
			for _, id := range CollectLValues(node.LHS) {
				env.declare(id.Name, kind, node)
			}
		case *build.IfStmt:
			declareLocalVariables(node.True, env)
			declareLocalVariables(node.False, env)
		case *build.ForStmt:
			for _, id := range CollectLValues(node.Vars) {
				env.declare(id.Name, Local, node)
			}
			declareLocalVariables(node.Body, env)
		}
	}
}

// WalkOnceWithEnvironment calls fct on every child of node, while maintaining the Environment of all available symbols.
func WalkOnceWithEnvironment(node build.Expr, env *Environment, fct func(e *build.Expr, env *Environment)) {
	env.Stack = append(env.Stack, node)
	switch node := node.(type) {
	case *build.File:
		declareGlobals(node.Stmt, env)
		build.WalkOnce(node, func(e *build.Expr) { fct(e, env) })
	case *build.DefStmt:
		env.enterBlock()
		env.Function = node
		declareParams(node, env)
		declareLocalVariables(node.Body, env)
		build.WalkOnce(node, func(e *build.Expr) { fct(e, env) })
		env.Function = nil
		env.exitBlock()
	case *build.Comprehension:
		env.enterBlock()
		for _, clause := range node.Clauses {
			switch clause := clause.(type) {
			case *build.ForClause:
				for _, id := range CollectLValues(clause.Vars) {
					env.declare(id.Name, Local, node)
				}
			}
		}
		build.WalkOnce(node, func(e *build.Expr) { fct(e, env) })
		env.exitBlock()
	default:
		build.WalkOnce(node, func(e *build.Expr) { fct(e, env) })
	}
	env.Stack = env.Stack[:len(env.Stack)-1]
}
