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

// IdentifierInfo holds information about an identifier in Go source.
type IdentifierInfo struct {
	Name  string
	Range Range
	File  File
	Type  struct {
		Range  Range
		Object types.Object
	}
	Declaration struct {
		Range  Range
		Object types.Object
	}

	ident            *ast.Ident
	wasEmbeddedField bool
}

// Identifier returns identifier information for a position
// in a file, accounting for a potentially incomplete selector.
func Identifier(ctx context.Context, v View, f File, pos token.Pos) (*IdentifierInfo, error) {
	if result, err := identifier(ctx, v, f, pos); err != nil || result != nil {
		return result, err
	}
	// 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.
	result, err := identifier(ctx, v, f, pos-1)
	if result == nil && err == nil {
		err = fmt.Errorf("no identifier found")
	}
	return result, err
}

func (i *IdentifierInfo) Hover(q types.Qualifier) (string, error) {
	if q == nil {
		fAST, err := i.File.GetAST()
		if err != nil {
			return "", err
		}
		pkg, err := i.File.GetPackage()
		if err != nil {
			return "", err
		}
		q = qualifier(fAST, pkg.Types, pkg.TypesInfo)
	}
	return types.ObjectString(i.Declaration.Object, q), nil
}

// identifier checks a single position for a potential identifier.
func identifier(ctx context.Context, v View, f File, pos token.Pos) (*IdentifierInfo, error) {
	fAST, err := f.GetAST()
	if err != nil {
		return nil, err
	}
	pkg, err := f.GetPackage()
	if err != nil {
		return nil, err
	}
	path, _ := astutil.PathEnclosingInterval(fAST, pos, pos)
	result := &IdentifierInfo{
		File: f,
	}
	if path == nil {
		return nil, 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 {
		return nil, nil
	}
	for _, n := range path[1:] {
		if field, ok := n.(*ast.Field); ok {
			result.wasEmbeddedField = len(field.Names) == 0
		}
	}
	result.Name = result.ident.Name
	result.Range = Range{Start: result.ident.Pos(), End: result.ident.End()}
	result.Declaration.Object = pkg.TypesInfo.ObjectOf(result.ident)
	if result.Declaration.Object == nil {
		return nil, fmt.Errorf("no object for ident %v", result.Name)
	}
	if result.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 := result.Declaration.Object.(*types.Var); ok {
			if n, ok := v.Type().(*types.Named); ok {
				result.Declaration.Object = n.Obj()
			}
		}
	}
	if result.Declaration.Range, err = objToRange(ctx, v, result.Declaration.Object); err != nil {
		return nil, err
	}
	typ := pkg.TypesInfo.TypeOf(result.ident)
	if typ == nil {
		return nil, fmt.Errorf("no type for %s", result.Name)
	}
	result.Type.Object = typeToObject(typ)
	if result.Type.Object != nil {
		if result.Type.Range, err = objToRange(ctx, v, result.Type.Object); err != nil {
			return nil, err
		}
	}
	return result, nil
}

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

func objToRange(ctx context.Context, v View, obj types.Object) (Range, error) {
	p := obj.Pos()
	if !p.IsValid() {
		return Range{}, fmt.Errorf("invalid position for %v", obj.Name())
	}
	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())),
	}, nil
}

// 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(rstambler): 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
		}
	}
}
