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

import (
	"fmt"
	"go/ast"
	"go/build"
	"go/token"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/ast/astutil"
)

// what reports all the information about the query selection that can be
// obtained from parsing only its containing source file.
// It is intended to be a very low-latency query callable from GUI
// tools, e.g. to populate a menu of options of slower queries about
// the selected location.
//
func what(q *Query) error {
	qpos, err := fastQueryPos(q.Build, q.Pos)
	if err != nil {
		return err
	}

	// (ignore errors)
	srcdir, importPath, _ := guessImportPath(qpos.fset.File(qpos.start).Name(), q.Build)

	// Determine which query modes are applicable to the selection.
	enable := map[string]bool{
		"describe": true, // any syntax; always enabled
	}

	if qpos.end > qpos.start {
		enable["freevars"] = true // nonempty selection?
	}

	for _, n := range qpos.path {
		switch n := n.(type) {
		case *ast.Ident:
			enable["definition"] = true
			enable["referrers"] = true
			enable["implements"] = true
		case *ast.CallExpr:
			enable["callees"] = true
		case *ast.FuncDecl:
			enable["callers"] = true
			enable["callstack"] = true
		case *ast.SendStmt:
			enable["peers"] = true
		case *ast.UnaryExpr:
			if n.Op == token.ARROW {
				enable["peers"] = true
			}
		}

		// For implements, we approximate findInterestingNode.
		if _, ok := enable["implements"]; !ok {
			switch n.(type) {
			case *ast.ArrayType,
				*ast.StructType,
				*ast.FuncType,
				*ast.InterfaceType,
				*ast.MapType,
				*ast.ChanType:
				enable["implements"] = true
			}
		}

		// For pointsto, we approximate findInterestingNode.
		if _, ok := enable["pointsto"]; !ok {
			switch n.(type) {
			case ast.Stmt,
				*ast.ArrayType,
				*ast.StructType,
				*ast.FuncType,
				*ast.InterfaceType,
				*ast.MapType,
				*ast.ChanType:
				enable["pointsto"] = false // not an expr

			case ast.Expr, ast.Decl, *ast.ValueSpec:
				enable["pointsto"] = true // an expr, maybe

			default:
				// Comment, Field, KeyValueExpr, etc: ascend.
			}
		}
	}

	// If we don't have an exact selection, disable modes that need one.
	if !qpos.exact {
		enable["callees"] = false
		enable["pointsto"] = false
		enable["whicherrs"] = false
		enable["describe"] = false
	}

	var modes []string
	for mode := range enable {
		modes = append(modes, mode)
	}
	sort.Strings(modes)

	// Find the object referred to by the selection (if it's an
	// identifier) and report the position of each identifier
	// that refers to the same object.
	//
	// This may return spurious matches (e.g. struct fields) because
	// it uses the best-effort name resolution done by go/parser.
	var sameids []token.Pos
	var object string
	if id, ok := qpos.path[0].(*ast.Ident); ok {
		if id.Obj == nil {
			// An unresolved identifier is potentially a package name.
			// Resolve them with a simple importer (adds ~100µs).
			importer := func(imports map[string]*ast.Object, path string) (*ast.Object, error) {
				pkg, ok := imports[path]
				if !ok {
					pkg = &ast.Object{
						Kind: ast.Pkg,
						Name: filepath.Base(path), // a guess
					}
					imports[path] = pkg
				}
				return pkg, nil
			}
			f := qpos.path[len(qpos.path)-1].(*ast.File)
			ast.NewPackage(qpos.fset, map[string]*ast.File{"": f}, importer, nil)
		}

		if id.Obj != nil {
			object = id.Obj.Name
			decl := qpos.path[len(qpos.path)-1]
			ast.Inspect(decl, func(n ast.Node) bool {
				if n, ok := n.(*ast.Ident); ok && n.Obj == id.Obj {
					sameids = append(sameids, n.Pos())
				}
				return true
			})
		}
	}

	q.Output(qpos.fset, &whatResult{
		path:       qpos.path,
		srcdir:     srcdir,
		importPath: importPath,
		modes:      modes,
		object:     object,
		sameids:    sameids,
	})
	return nil
}

// guessImportPath finds the package containing filename, and returns
// its source directory (an element of $GOPATH) and its import path
// relative to it.
//
// TODO(adonovan): what about _test.go files that are not part of the
// package?
//
func guessImportPath(filename string, buildContext *build.Context) (srcdir, importPath string, err error) {
	absFile, err := filepath.Abs(filename)
	if err != nil {
		return "", "", fmt.Errorf("can't form absolute path of %s: %v", filename, err)
	}

	absFileDir := filepath.Dir(absFile)
	resolvedAbsFileDir, err := filepath.EvalSymlinks(absFileDir)
	if err != nil {
		return "", "", fmt.Errorf("can't evaluate symlinks of %s: %v", absFileDir, err)
	}

	segmentedAbsFileDir := segments(resolvedAbsFileDir)
	// Find the innermost directory in $GOPATH that encloses filename.
	minD := 1024
	for _, gopathDir := range buildContext.SrcDirs() {
		absDir, err := filepath.Abs(gopathDir)
		if err != nil {
			continue // e.g. non-existent dir on $GOPATH
		}
		resolvedAbsDir, err := filepath.EvalSymlinks(absDir)
		if err != nil {
			continue // e.g. non-existent dir on $GOPATH
		}

		d := prefixLen(segments(resolvedAbsDir), segmentedAbsFileDir)
		// If there are multiple matches,
		// prefer the innermost enclosing directory
		// (smallest d).
		if d >= 0 && d < minD {
			minD = d
			srcdir = gopathDir
			importPath = strings.Join(segmentedAbsFileDir[len(segmentedAbsFileDir)-minD:], string(os.PathSeparator))
		}
	}
	if srcdir == "" {
		return "", "", fmt.Errorf("directory %s is not beneath any of these GOROOT/GOPATH directories: %s",
			filepath.Dir(absFile), strings.Join(buildContext.SrcDirs(), ", "))
	}
	if importPath == "" {
		// This happens for e.g. $GOPATH/src/a.go, but
		// "" is not a valid path for (*go/build).Import.
		return "", "", fmt.Errorf("cannot load package in root of source directory %s", srcdir)
	}
	return srcdir, importPath, nil
}

func segments(path string) []string {
	return strings.Split(path, string(os.PathSeparator))
}

// prefixLen returns the length of the remainder of y if x is a prefix
// of y, a negative number otherwise.
func prefixLen(x, y []string) int {
	d := len(y) - len(x)
	if d >= 0 {
		for i := range x {
			if y[i] != x[i] {
				return -1 // not a prefix
			}
		}
	}
	return d
}

type whatResult struct {
	path       []ast.Node
	modes      []string
	srcdir     string
	importPath string
	object     string
	sameids    []token.Pos
}

func (r *whatResult) PrintPlain(printf printfFunc) {
	for _, n := range r.path {
		printf(n, "%s", astutil.NodeDescription(n))
	}
	printf(nil, "modes: %s", r.modes)
	printf(nil, "srcdir: %s", r.srcdir)
	printf(nil, "import path: %s", r.importPath)
	for _, pos := range r.sameids {
		printf(pos, "%s", r.object)
	}
}

func (r *whatResult) JSON(fset *token.FileSet) []byte {
	var enclosing []serial.SyntaxNode
	for _, n := range r.path {
		enclosing = append(enclosing, serial.SyntaxNode{
			Description: astutil.NodeDescription(n),
			Start:       fset.Position(n.Pos()).Offset,
			End:         fset.Position(n.End()).Offset,
		})
	}

	var sameids []string
	for _, pos := range r.sameids {
		sameids = append(sameids, fset.Position(pos).String())
	}

	return toJSON(&serial.What{
		Modes:      r.modes,
		SrcDir:     r.srcdir,
		ImportPath: r.importPath,
		Enclosing:  enclosing,
		Object:     r.object,
		SameIDs:    sameids,
	})
}
