// Copyright 2016 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The importers package uses go/ast to analyze Go packages or Go files
// and collect references to types whose package has a package prefix.
// It is used by the language specific importers to determine the set of
// wrapper types to be generated.
//
// For example, in the Go file
//
// package javaprogram
//
// import "Java/java/lang"
//
// func F() {
//     o := lang.Object.New()
//     ...
// }
//
// the java importer uses this package to determine that the "java/lang"
// package and the wrapper interface, lang.Object, needs to be generated.
// After calling AnalyzeFile or AnalyzePackages, the References result
// contains the reference to lang.Object and the names set will contain
// "New".
package importers

import (
	"errors"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

// References is the result of analyzing a Go file or set of Go packages.
//
// For example, the Go file
//
// package pkg
//
// import "Prefix/some/Package"
//
// var A = Package.Identifier
//
// Will result in a single PkgRef with the "some/Package" package and
// the Identifier name. The Names set will contain the single name,
// "Identifier".
type References struct {
	// The list of references to identifiers in packages that are
	// identified by a package prefix.
	Refs []PkgRef
	// The list of names used in at least one selector expression.
	// Useful as a conservative upper bound on the set of identifiers
	// referenced from a set of packages.
	Names map[string]struct{}
	// Embedders is a list of struct types with prefixed types
	// embedded.
	Embedders []Struct
}

// Struct is a representation of a struct type with embedded
// types.
type Struct struct {
	Name    string
	Pkg     string
	PkgPath string
	Refs    []PkgRef
}

// PkgRef is a reference to an identifier in a package.
type PkgRef struct {
	Name string
	Pkg  string
}

type refsSaver struct {
	pkgPrefix string
	*References
	refMap       map[PkgRef]struct{}
	insideStruct bool
}

// AnalyzeFile scans the provided file for references to packages with the given
// package prefix. The list of unique (package, identifier) pairs is returned
func AnalyzeFile(file *ast.File, pkgPrefix string) (*References, error) {
	visitor := newRefsSaver(pkgPrefix)
	fset := token.NewFileSet()
	files := map[string]*ast.File{file.Name.Name: file}
	// Ignore errors (from unknown packages)
	pkg, _ := ast.NewPackage(fset, files, visitor.importer(), nil)
	ast.Walk(visitor, pkg)
	visitor.findEmbeddingStructs("", pkg)
	return visitor.References, nil
}

// AnalyzePackages scans the provided packages for references to packages with the given
// package prefix. The list of unique (package, identifier) pairs is returned
func AnalyzePackages(pkgs []*build.Package, pkgPrefix string) (*References, error) {
	visitor := newRefsSaver(pkgPrefix)
	imp := visitor.importer()
	fset := token.NewFileSet()
	for _, pkg := range pkgs {
		fileNames := append(append([]string{}, pkg.GoFiles...), pkg.CgoFiles...)
		files := make(map[string]*ast.File)
		for _, name := range fileNames {
			f, err := parser.ParseFile(fset, filepath.Join(pkg.Dir, name), nil, 0)
			if err != nil {
				return nil, err
			}
			files[name] = f
		}
		// Ignore errors (from unknown packages)
		astpkg, _ := ast.NewPackage(fset, files, imp, nil)
		ast.Walk(visitor, astpkg)
		visitor.findEmbeddingStructs(pkg.ImportPath, astpkg)
	}
	return visitor.References, nil
}

// findEmbeddingStructs finds all top level declarations embedding a prefixed type.
//
// For example:
//
// import "Prefix/some/Package"
//
// type T struct {
//     Package.Class
// }
func (v *refsSaver) findEmbeddingStructs(pkgpath string, pkg *ast.Package) {
	var names []string
	for _, obj := range pkg.Scope.Objects {
		if obj.Kind != ast.Typ || !ast.IsExported(obj.Name) {
			continue
		}
		names = append(names, obj.Name)
	}
	sort.Strings(names)
	for _, name := range names {
		obj := pkg.Scope.Objects[name]

		t, ok := obj.Decl.(*ast.TypeSpec).Type.(*ast.StructType)
		if !ok {
			continue
		}
		var refs []PkgRef
		for _, f := range t.Fields.List {
			if len(f.Names) > 0 && !f.Names[0].IsExported() {
				continue
			}
			sel, ok := f.Type.(*ast.SelectorExpr)
			if !ok {
				continue
			}
			if ref, ok := v.parseRef(sel); ok {
				refs = append(refs, ref)
			}
		}
		if len(refs) > 0 {
			v.Embedders = append(v.Embedders, Struct{
				Name:    obj.Name,
				Pkg:     pkg.Name,
				PkgPath: pkgpath,

				Refs: refs,
			})
		}
	}
}

func newRefsSaver(pkgPrefix string) *refsSaver {
	s := &refsSaver{
		pkgPrefix:  pkgPrefix,
		refMap:     make(map[PkgRef]struct{}),
		References: &References{},
	}
	s.Names = make(map[string]struct{})
	return s
}

func (v *refsSaver) importer() ast.Importer {
	return func(imports map[string]*ast.Object, pkgPath string) (*ast.Object, error) {
		if pkg, exists := imports[pkgPath]; exists {
			return pkg, nil
		}
		if !strings.HasPrefix(pkgPath, v.pkgPrefix) {
			return nil, errors.New("ignored")
		}
		pkg := ast.NewObj(ast.Pkg, path.Base(pkgPath))
		imports[pkgPath] = pkg
		return pkg, nil
	}
}

func (v *refsSaver) parseRef(sel *ast.SelectorExpr) (PkgRef, bool) {
	x, ok := sel.X.(*ast.Ident)
	if !ok || x.Obj == nil {
		return PkgRef{}, false
	}
	imp, ok := x.Obj.Decl.(*ast.ImportSpec)
	if !ok {
		return PkgRef{}, false
	}
	pkgPath, err := strconv.Unquote(imp.Path.Value)
	if err != nil {
		return PkgRef{}, false
	}
	if !strings.HasPrefix(pkgPath, v.pkgPrefix) {
		return PkgRef{}, false
	}
	pkgPath = pkgPath[len(v.pkgPrefix):]
	return PkgRef{Pkg: pkgPath, Name: sel.Sel.Name}, true
}

func (v *refsSaver) Visit(n ast.Node) ast.Visitor {
	switch n := n.(type) {
	case *ast.StructType:
		// Use a copy of refsSaver that only accepts exported fields. It refers
		// to the original refsSaver for collecting references.
		v2 := *v
		v2.insideStruct = true
		return &v2
	case *ast.Field:
		if v.insideStruct && len(n.Names) == 1 && !n.Names[0].IsExported() {
			return nil
		}
	case *ast.SelectorExpr:
		v.Names[n.Sel.Name] = struct{}{}
		if ref, ok := v.parseRef(n); ok {
			if _, exists := v.refMap[ref]; !exists {
				v.refMap[ref] = struct{}{}
				v.Refs = append(v.Refs, ref)
			}
			return nil
		}
	case *ast.FuncDecl:
		if n.Recv != nil { // Methods
			v.Names[n.Name.Name] = struct{}{}
		}
	}
	return v
}
