// Copyright 2018 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 source

import (
	"bytes"
	"context"
	"fmt"
	"go/ast"
	"go/token"
	"go/types"

	"golang.org/x/tools/go/ast/astutil"
)

func Definition(ctx context.Context, v View, f File, pos token.Pos) (Range, error) {
	fAST, err := f.GetAST()
	if err != nil {
		return Range{}, err
	}
	pkg, err := f.GetPackage()
	if err != nil {
		return Range{}, err
	}
	i, err := findIdentifier(fAST, pos)
	if err != nil {
		return Range{}, err
	}
	if i.ident == nil {
		return Range{}, fmt.Errorf("not a valid identifier")
	}
	obj := pkg.TypesInfo.ObjectOf(i.ident)
	if obj == nil {
		return Range{}, fmt.Errorf("no object")
	}
	if i.wasEmbeddedField {
		// the original position was on the embedded field declaration
		// so we try to dig out the type and jump to that instead
		if v, ok := obj.(*types.Var); ok {
			if n, ok := v.Type().(*types.Named); ok {
				obj = n.Obj()
			}
		}
	}
	return objToRange(ctx, v, obj), nil
}

func TypeDefinition(ctx context.Context, v View, f File, pos token.Pos) (Range, error) {
	fAST, err := f.GetAST()
	if err != nil {
		return Range{}, err
	}
	pkg, err := f.GetPackage()
	if err != nil {
		return Range{}, err
	}
	i, err := findIdentifier(fAST, pos)
	if err != nil {
		return Range{}, err
	}
	if i.ident == nil {
		return Range{}, fmt.Errorf("not a valid identifier")
	}
	typ := pkg.TypesInfo.TypeOf(i.ident)
	if typ == nil {
		return Range{}, fmt.Errorf("no type for %s", i.ident.Name)
	}
	obj := typeToObject(typ)
	if obj == nil {
		return Range{}, fmt.Errorf("no object for type %s", typ.String())
	}
	return objToRange(ctx, v, obj), nil
}

func typeToObject(typ types.Type) (obj types.Object) {
	switch typ := typ.(type) {
	case *types.Named:
		obj = typ.Obj()
	case *types.Pointer:
		obj = typeToObject(typ.Elem())
	}
	return obj
}

// ident returns the ident plus any extra information needed
type ident struct {
	ident            *ast.Ident
	wasEmbeddedField bool
}

// findIdentifier returns the ast.Ident for a position
// in a file, accounting for a potentially incomplete selector.
func findIdentifier(f *ast.File, pos token.Pos) (ident, error) {
	m, err := checkIdentifier(f, pos)
	if err != nil {
		return ident{}, err
	}
	if m.ident != nil {
		return m, nil
	}
	// If the position is not an identifier but immediately follows
	// an identifier or selector period (as is common when
	// requesting a completion), use the path to the preceding node.
	return checkIdentifier(f, pos-1)
}

// checkIdentifier checks a single position for a potential identifier.
func checkIdentifier(f *ast.File, pos token.Pos) (ident, error) {
	path, _ := astutil.PathEnclosingInterval(f, pos, pos)
	result := ident{}
	if path == nil {
		return result, fmt.Errorf("can't find node enclosing position")
	}
	switch node := path[0].(type) {
	case *ast.Ident:
		result.ident = node
	case *ast.SelectorExpr:
		result.ident = node.Sel
	}
	if result.ident != nil {
		for _, n := range path[1:] {
			if field, ok := n.(*ast.Field); ok {
				result.wasEmbeddedField = len(field.Names) == 0
			}
		}
	}
	return result, nil
}

func objToRange(ctx context.Context, v View, obj types.Object) Range {
	p := obj.Pos()
	tok := v.FileSet().File(p)
	pos := tok.Position(p)
	if pos.Column == 1 {
		// We do not have full position information because exportdata does not
		// store the column. For now, we attempt to read the original source
		// and find the identifier within the line. If we find it, we patch the
		// column to match its offset.
		//
		// TODO: If we parse from source, we will never need this hack.
		f, err := v.GetFile(ctx, ToURI(pos.Filename))
		if err != nil {
			goto Return
		}
		src, err := f.Read()
		if err != nil {
			goto Return
		}
		tok, err := f.GetToken()
		if err != nil {
			goto Return
		}
		start := lineStart(tok, pos.Line)
		offset := tok.Offset(start)
		col := bytes.Index(src[offset:], []byte(obj.Name()))
		p = tok.Pos(offset + col)
	}
Return:
	return Range{
		Start: p,
		End:   p + token.Pos(identifierLen(obj.Name())),
	}
}

// TODO: This needs to be fixed to address golang.org/issue/29149.
func identifierLen(ident string) int {
	return len([]byte(ident))
}

// this functionality was borrowed from the analysisutil package
func lineStart(f *token.File, line int) token.Pos {
	// Use binary search to find the start offset of this line.
	//
	// TODO(adonovan): eventually replace this function with the
	// simpler and more efficient (*go/token.File).LineStart, added
	// in go1.12.

	min := 0        // inclusive
	max := f.Size() // exclusive
	for {
		offset := (min + max) / 2
		pos := f.Pos(offset)
		posn := f.Position(pos)
		if posn.Line == line {
			return pos - (token.Pos(posn.Column) - 1)
		}

		if min+1 >= max {
			return token.NoPos
		}

		if posn.Line < line {
			min = offset
		} else {
			max = offset
		}
	}
}
