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

import (
	"path"
	"strconv"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/internal"
)

// TODO(resolve): this is also done in compile, do we need both?
func (r *Runtime) ResolveFiles(p *build.Instance) (errs errors.Error) {
	idx := r.index

	// Link top-level declarations. As top-level entries get unified, an entry
	// may be linked to any top-level entry of any of the files.
	allFields := map[string]ast.Node{}
	for _, f := range p.Files {
		if p := internal.GetPackageInfo(f); p.IsAnonymous() {
			continue
		}
		for _, d := range f.Decls {
			if f, ok := d.(*ast.Field); ok && f.Value != nil {
				if ident, ok := f.Label.(*ast.Ident); ok {
					allFields[ident.Name] = f.Value
				}
			}
		}
	}
	for _, f := range p.Files {
		if p := internal.GetPackageInfo(f); p.IsAnonymous() {
			continue
		}
		err := resolveFile(idx, f, p, allFields)
		errs = errors.Append(errs, err)
	}
	return errs
}

func resolveFile(
	idx *index,
	f *ast.File,
	p *build.Instance,
	allFields map[string]ast.Node,
) errors.Error {
	unresolved := map[string][]*ast.Ident{}
	for _, u := range f.Unresolved {
		unresolved[u.Name] = append(unresolved[u.Name], u)
	}
	fields := map[string]ast.Node{}
	for _, d := range f.Decls {
		if f, ok := d.(*ast.Field); ok && f.Value != nil {
			if ident, ok := f.Label.(*ast.Ident); ok {
				fields[ident.Name] = d
			}
		}
	}
	var errs errors.Error

	specs := []*ast.ImportSpec{}

	for _, spec := range f.Imports {
		id, err := strconv.Unquote(spec.Path.Value)
		if err != nil {
			continue // quietly ignore the error
		}
		name := path.Base(id)
		if imp := p.LookupImport(id); imp != nil {
			name = imp.PkgName
		} else if _, ok := idx.builtins[id]; !ok {
			errs = errors.Append(errs,
				nodeErrorf(spec, "package %q not found", id))
			continue
		}
		if spec.Name != nil {
			name = spec.Name.Name
		}
		if n, ok := fields[name]; ok {
			errs = errors.Append(errs, nodeErrorf(spec,
				"%s redeclared as imported package name\n"+
					"\tprevious declaration at %v", name, lineStr(idx, n)))
			continue
		}
		fields[name] = spec
		used := false
		for _, u := range unresolved[name] {
			used = true
			u.Node = spec
		}
		if !used {
			specs = append(specs, spec)
		}
	}

	// Verify each import is used.
	if len(specs) > 0 {
		// Find references to imports. This assumes that identifiers in labels
		// are not resolved or that such errors are caught elsewhere.
		ast.Walk(f, nil, func(n ast.Node) {
			if x, ok := n.(*ast.Ident); ok {
				// As we also visit labels, most nodes will be nil.
				if x.Node == nil {
					return
				}
				for i, s := range specs {
					if s == x.Node {
						specs[i] = nil
						return
					}
				}
			}
		})

		// Add errors for unused imports.
		for _, spec := range specs {
			if spec == nil {
				continue
			}
			if spec.Name == nil {
				errs = errors.Append(errs, nodeErrorf(spec,
					"imported and not used: %s", spec.Path.Value))
			} else {
				errs = errors.Append(errs, nodeErrorf(spec,
					"imported and not used: %s as %s", spec.Path.Value, spec.Name))
			}
		}
	}

	k := 0
	for _, u := range f.Unresolved {
		if u.Node != nil {
			continue
		}
		if n, ok := allFields[u.Name]; ok {
			u.Node = n
			u.Scope = f
			continue
		}
		f.Unresolved[k] = u
		k++
	}
	f.Unresolved = f.Unresolved[:k]
	// TODO: also need to resolve types.
	// if len(f.Unresolved) > 0 {
	// 	n := f.Unresolved[0]
	// 	return ctx.mkErr(newBase(n), "unresolved reference %s", n.Name)
	// }
	return errs
}

func lineStr(idx *index, n ast.Node) string {
	return n.Pos().String()
}
