// Copyright 2013 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.

package oracle

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"
	"io/ioutil"
	"sort"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/types"
	"golang.org/x/tools/oracle/serial"
	"golang.org/x/tools/refactor/importgraph"
)

// Referrers reports all identifiers that resolve to the same object
// as the queried identifier, within any package in the analysis scope.
func referrers(q *Query) error {
	lconf := loader.Config{Build: q.Build}
	allowErrors(&lconf)

	if err := importQueryPackage(q.Pos, &lconf); err != nil {
		return err
	}

	var id *ast.Ident
	var obj types.Object
	var lprog *loader.Program
	var pass2 bool
	var qpos *queryPos
	for {
		// Load/parse/type-check the program.
		var err error
		lprog, err = lconf.Load()
		if err != nil {
			return err
		}
		q.Fset = lprog.Fset

		qpos, err = parseQueryPos(lprog, q.Pos, false)
		if err != nil {
			return err
		}

		id, _ = qpos.path[0].(*ast.Ident)
		if id == nil {
			return fmt.Errorf("no identifier here")
		}

		obj = qpos.info.ObjectOf(id)
		if obj == nil {
			// Happens for y in "switch y := x.(type)",
			// the package declaration,
			// and unresolved identifiers.
			if _, ok := qpos.path[1].(*ast.File); ok { // package decl?
				pkg := qpos.info.Pkg
				obj = types.NewPkgName(id.Pos(), pkg, pkg.Name(), pkg)
			} else {
				return fmt.Errorf("no object for identifier: %T", qpos.path[1])
			}
		}

		if pass2 {
			break
		}

		// If the identifier is exported, we must load all packages that
		// depend transitively upon the package that defines it.
		// Treat PkgNames as exported, even though they're lowercase.
		if _, isPkg := obj.(*types.PkgName); !(isPkg || obj.Exported()) {
			break // not exported
		}

		// Scan the workspace and build the import graph.
		// Ignore broken packages.
		_, rev, _ := importgraph.Build(q.Build)

		// Re-load the larger program.
		// Create a new file set so that ...
		// External test packages are never imported,
		// so they will never appear in the graph.
		// (We must reset the Config here, not just reset the Fset field.)
		lconf = loader.Config{
			Fset:  token.NewFileSet(),
			Build: q.Build,
		}
		allowErrors(&lconf)
		for path := range rev.Search(obj.Pkg().Path()) {
			lconf.ImportWithTests(path)
		}
		pass2 = true
	}

	// Iterate over all go/types' Uses facts for the entire program.
	var refs []*ast.Ident
	for _, info := range lprog.AllPackages {
		for id2, obj2 := range info.Uses {
			if sameObj(obj, obj2) {
				refs = append(refs, id2)
			}
		}
	}
	sort.Sort(byNamePos{q.Fset, refs})

	q.result = &referrersResult{
		qpos:  qpos,
		query: id,
		obj:   obj,
		refs:  refs,
	}
	return nil
}

// same reports whether x and y are identical, or both are PkgNames
// that import the same Package.
//
func sameObj(x, y types.Object) bool {
	if x == y {
		return true
	}
	if x, ok := x.(*types.PkgName); ok {
		if y, ok := y.(*types.PkgName); ok {
			return x.Imported() == y.Imported()
		}
	}
	return false
}

// -------- utils --------

// An deterministic ordering for token.Pos that doesn't
// depend on the order in which packages were loaded.
func lessPos(fset *token.FileSet, x, y token.Pos) bool {
	fx := fset.File(x)
	fy := fset.File(y)
	if fx != fy {
		return fx.Name() < fy.Name()
	}
	return x < y
}

type byNamePos struct {
	fset *token.FileSet
	ids  []*ast.Ident
}

func (p byNamePos) Len() int      { return len(p.ids) }
func (p byNamePos) Swap(i, j int) { p.ids[i], p.ids[j] = p.ids[j], p.ids[i] }
func (p byNamePos) Less(i, j int) bool {
	return lessPos(p.fset, p.ids[i].NamePos, p.ids[j].NamePos)
}

type referrersResult struct {
	qpos  *queryPos
	query *ast.Ident   // identifier of query
	obj   types.Object // object it denotes
	refs  []*ast.Ident // set of all other references to it
}

func (r *referrersResult) display(printf printfFunc) {
	printf(r.obj, "%d references to %s", len(r.refs), r.qpos.objectString(r.obj))

	// Show referring lines, like grep.
	type fileinfo struct {
		refs     []*ast.Ident
		linenums []int       // line number of refs[i]
		data     chan []byte // file contents
	}
	var fileinfos []*fileinfo
	fileinfosByName := make(map[string]*fileinfo)

	// First pass: start the file reads concurrently.
	for _, ref := range r.refs {
		posn := r.qpos.fset.Position(ref.Pos())
		fi := fileinfosByName[posn.Filename]
		if fi == nil {
			fi = &fileinfo{data: make(chan []byte)}
			fileinfosByName[posn.Filename] = fi
			fileinfos = append(fileinfos, fi)

			// First request for this file:
			// start asynchronous read.
			go func() {
				content, err := ioutil.ReadFile(posn.Filename)
				if err != nil {
					content = []byte(fmt.Sprintf("error: %v", err))
				}
				fi.data <- content
			}()
		}
		fi.refs = append(fi.refs, ref)
		fi.linenums = append(fi.linenums, posn.Line)
	}

	// Second pass: print refs in original order.
	// One line may have several refs at different columns.
	for _, fi := range fileinfos {
		content := <-fi.data // wait for I/O completion
		lines := bytes.Split(content, []byte("\n"))
		for i, ref := range fi.refs {
			printf(ref, "%s", lines[fi.linenums[i]-1])
		}
	}
}

// TODO(adonovan): encode extent, not just Pos info, in Serial form.

func (r *referrersResult) toSerial(res *serial.Result, fset *token.FileSet) {
	referrers := &serial.Referrers{
		Pos:  fset.Position(r.query.Pos()).String(),
		Desc: r.obj.String(),
	}
	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
		referrers.ObjPos = fset.Position(pos).String()
	}
	for _, ref := range r.refs {
		referrers.Refs = append(referrers.Refs, fset.Position(ref.NamePos).String())
	}
	res.Referrers = referrers
}
