// 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
	Refs []PkgRef
}

// PkgRef is a reference to an identifier in a package.
type PkgRef struct {
	Pkg  string
	Name 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(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(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,

				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
}
