// 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"
	"io/ioutil"

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

func Definition(ctx context.Context, 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()
			}
		}
	}
	fset, err := f.GetFileSet()
	if err != nil {
		return Range{}, err
	}
	return objToRange(fset, obj), nil
}

func TypeDefinition(ctx context.Context, 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())
	}
	fset, err := f.GetFileSet()
	if err != nil {
		return Range{}, err
	}
	return objToRange(fset, 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(fSet *token.FileSet, obj types.Object) Range {
	p := obj.Pos()
	f := fSet.File(p)
	pos := f.Position(p)
	if pos.Column == 1 {
		// Column is 1, so we probably do not have full position information
		// Currently 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: we have probably already added the full data for the file to the
		// fileset, we ought to track it rather than adding it over and over again
		// TODO: if we parse from source, we will never need this hack
		if src, err := ioutil.ReadFile(pos.Filename); err == nil {
			newF := fSet.AddFile(pos.Filename, -1, len(src))
			newF.SetLinesForContent(src)
			lineStart := lineStart(newF, pos.Line)
			offset := newF.Offset(lineStart)
			col := bytes.Index(src[offset:], []byte(obj.Name()))
			p = newF.Pos(offset + col)
		}
	}
	return Range{
		Start: p,
		End:   p + token.Pos(len([]byte(obj.Name()))), // TODO: use real range of obj
	}
}

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