// Copyright 2018 The 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.

// This file implements scopes and the objects they contain.

package astutil

import (
	"bytes"
	"fmt"

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

// An ErrFunc processes errors.
type ErrFunc func(pos token.Pos, msg string, args ...interface{})

// Resolve resolves all identifiers in a file. Unresolved identifiers are
// recorded in Unresolved.
func Resolve(f *ast.File, errFn ErrFunc) {
	walk(&scope{errFn: errFn}, f)
}

func ResolveExpr(e ast.Expr, errFn ErrFunc) {
	f := &ast.File{}
	walk(&scope{file: f, errFn: errFn}, e)
}

// A Scope maintains the set of named language entities declared
// in the scope and a link to the immediately surrounding (outer)
// scope.
//
type scope struct {
	file  *ast.File
	outer *scope
	node  ast.Node
	index map[string]ast.Node

	errFn func(p token.Pos, msg string, args ...interface{})
}

func newScope(f *ast.File, outer *scope, node ast.Node, decls []ast.Decl) *scope {
	const n = 4 // initial scope capacity
	s := &scope{
		file:  f,
		outer: outer,
		node:  node,
		index: make(map[string]ast.Node, n),
		errFn: outer.errFn,
	}
	for _, d := range decls {
		switch x := d.(type) {
		case *ast.Field:
			name, _ := internal.LabelName(x.Label)
			s.insert(name, x.Value)
		case *ast.Alias:
			name, _ := internal.LabelName(x.Ident)
			s.insert(name, x)
			// Handle imports
		}
	}
	return s
}

func (s *scope) insert(name string, n ast.Node) {
	if name == "" {
		return
	}
	if _, existing := s.lookup(name); existing != nil {
		_, isAlias1 := n.(*ast.Alias)
		_, isAlias2 := existing.(*ast.Alias)
		if isAlias1 != isAlias2 {
			s.errFn(n.Pos(), "cannot have alias and non-alias with the same name")
			return
		} else if isAlias1 || isAlias2 {
			s.errFn(n.Pos(), "cannot have two aliases with the same name in the same scope")
			return
		}
	}
	s.index[name] = n
}

func (s *scope) lookup(name string) (obj, node ast.Node) {
	last := s
	for s != nil {
		if n, ok := s.index[name]; ok {
			if last.node == n {
				return nil, n
			}
			return s.node, n
		}
		s, last = s.outer, s
	}
	return nil, nil
}

func (s *scope) After(n ast.Node) {}
func (s *scope) Before(n ast.Node) (w visitor) {
	switch x := n.(type) {
	case *ast.File:
		s := newScope(x, s, x, x.Decls)
		// Support imports.
		for _, d := range x.Decls {
			walk(s, d)
		}
		return nil

	case *ast.StructLit:
		return newScope(s.file, s, x, x.Elts)

	case *ast.Comprehension:
		s = scopeClauses(s, x.Clauses)

	case *ast.ListComprehension:
		s = scopeClauses(s, x.Clauses)

	case *ast.Field:
		switch label := x.Label.(type) {
		case *ast.Interpolation:
			walk(s, label)
		case *ast.TemplateLabel:
			s := newScope(s.file, s, x, nil)
			name, _ := internal.LabelName(label)
			s.insert(name, x.Label) // Field used for entire lambda.
			walk(s, x.Value)
			return nil
		}
		// Disallow referring to the current LHS name (this applies recursively)
		if x.Value != nil {
			walk(s, x.Value)
		}
		return nil

	case *ast.Alias:
		// Disallow referring to the current LHS name.
		name := x.Ident.Name
		saved := s.index[name]
		delete(s.index, name) // The same name may still appear in another scope

		if x.Expr != nil {
			walk(s, x.Expr)
		}
		s.index[name] = saved
		return nil

	case *ast.ImportSpec:
		return nil

	case *ast.SelectorExpr:
		walk(s, x.X)
		return nil

	case *ast.Ident:
		name, ok := internal.LabelName(x)
		if !ok {
			break
		}
		if obj, node := s.lookup(name); node != nil {
			x.Node = node
			x.Scope = obj
		} else {
			s.file.Unresolved = append(s.file.Unresolved, x)
		}
		return nil
	}
	return s
}

func scopeClauses(s *scope, clauses []ast.Clause) *scope {
	for _, c := range clauses {
		if f, ok := c.(*ast.ForClause); ok { // TODO(let): support let clause
			walk(s, f.Source)
			s = newScope(s.file, s, f, nil)
			if f.Key != nil {
				name, _ := internal.LabelName(f.Key)
				s.insert(name, f.Key)
			}
			name, _ := internal.LabelName(f.Value)
			s.insert(name, f.Value)
		} else {
			walk(s, c)
		}
	}
	return s
}

// Debugging support
func (s *scope) String() string {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "scope %p {", s)
	if s != nil && len(s.index) > 0 {
		fmt.Fprintln(&buf)
		for name := range s.index {
			fmt.Fprintf(&buf, "\t%v\n", name)
		}
	}
	fmt.Fprintf(&buf, "}\n")
	return buf.String()
}
