// 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"
	"os"
	"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"
)

// TODO(adonovan): use golang.org/x/tools/refactor/importgraph to choose
// the scope automatically.

// 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
	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)", but I think that's all.
			return fmt.Errorf("no object for identifier")
		}

		// If the identifier is exported, we must load all packages that
		// depend transitively upon the package that defines it.
		//
		// TODO(adonovan): opt: skip this step if obj.Pkg() is a test or
		// main package.
		if pass2 || !obj.Exported() {
			break
		}

		// Scan the workspace and build the import graph.
		_, rev, errors := importgraph.Build(q.Build)
		if len(errors) > 0 {
			for path, err := range errors {
				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
			}
			return fmt.Errorf("failed to scan import graph for workspace")
		}

		// 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{
		fset:  q.Fset,
		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 {
	fset  *token.FileSet
	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.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.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
}
