// Copyright 2019 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.

// The code in this file is based largely on the code in
// cmd/guru/implements.go. The guru implementation supports
// looking up "implementers" of methods also, but that
// code has been cut out here for now for simplicity.

package source

import (
	"context"
	"go/types"
	"sort"

	"golang.org/x/tools/go/types/typeutil"
	"golang.org/x/tools/internal/lsp/protocol"
)

func Implementation(ctx context.Context, view View, f File, position protocol.Position) ([]protocol.Location, error) {
	// Find all references to the identifier at the position.
	ident, err := Identifier(ctx, view, f, position)
	if err != nil {
		return nil, err
	}

	res, err := ident.implementations(ctx)
	if err != nil {
		return nil, err
	}

	var locations []protocol.Location
	for _, t := range res.to {
		// We'll provide implementations that are named types and pointers to named types.
		if p, ok := t.(*types.Pointer); ok {
			t = p.Elem()
		}
		if n, ok := t.(*types.Named); ok {
			ph, pkg, err := view.FindFileInPackage(ctx, f.URI(), ident.pkg)
			if err != nil {
				return nil, err
			}
			f, _, _, err := ph.Cached()
			if err != nil {
				return nil, err
			}
			ident, err := findIdentifier(ctx, view.Snapshot(), pkg, f, n.Obj().Pos())
			if err != nil {
				return nil, err
			}
			decRange, err := ident.Declaration.Range()
			if err != nil {
				return nil, err
			}
			locations = append(locations, protocol.Location{
				URI:   protocol.NewURI(ident.Declaration.URI()),
				Range: decRange,
			})
		}
	}

	return locations, nil
}

func (i *IdentifierInfo) implementations(ctx context.Context) (implementsResult, error) {
	T := i.Type.Object.Type()

	// Find all named types, even local types (which can have
	// methods due to promotion) and the built-in "error".
	// We ignore aliases 'type M = N' to avoid duplicate
	// reporting of the Named type N.
	var allNamed []*types.Named
	info := i.pkg.GetTypesInfo()
	for _, obj := range info.Defs {
		if obj, ok := obj.(*types.TypeName); ok && !obj.IsAlias() {
			if named, ok := obj.Type().(*types.Named); ok {
				allNamed = append(allNamed, named)
			}
		}
	}

	allNamed = append(allNamed, types.Universe.Lookup("error").Type().(*types.Named))

	var msets typeutil.MethodSetCache

	// TODO(matloob): We only use the to result for now. Figure out if we want to
	// surface the from and fromPtr results to users.
	// Test each named type.
	var to, from, fromPtr []types.Type
	for _, U := range allNamed {
		if isInterface(T) {
			if msets.MethodSet(T).Len() == 0 {
				continue // empty interface
			}
			if isInterface(U) {
				if msets.MethodSet(U).Len() == 0 {
					continue // empty interface
				}

				// T interface, U interface
				if !types.Identical(T, U) {
					if types.AssignableTo(U, T) {
						to = append(to, U)
					}
					if types.AssignableTo(T, U) {
						from = append(from, U)
					}
				}
			} else {
				// T interface, U concrete
				if types.AssignableTo(U, T) {
					to = append(to, U)
				} else if pU := types.NewPointer(U); types.AssignableTo(pU, T) {
					to = append(to, pU)
				}
			}
		} else if isInterface(U) {
			if msets.MethodSet(U).Len() == 0 {
				continue // empty interface
			}

			// T concrete, U interface
			if types.AssignableTo(T, U) {
				from = append(from, U)
			} else if pT := types.NewPointer(T); types.AssignableTo(pT, U) {
				fromPtr = append(fromPtr, U)
			}
		}
	}

	// Sort types (arbitrarily) to ensure test determinism.
	sort.Sort(typesByString(to))
	sort.Sort(typesByString(from))
	sort.Sort(typesByString(fromPtr))

	// TODO(matloob): Perhaps support calling implements on methods instead of just interface types,
	// as guru does.

	return implementsResult{to, from, fromPtr}, nil
}

// implementsResult contains the results of an implements query.
type implementsResult struct {
	to      []types.Type // named or ptr-to-named types assignable to interface T
	from    []types.Type // named interfaces assignable from T
	fromPtr []types.Type // named interfaces assignable only from *T
}

type typesByString []types.Type

func (p typesByString) Len() int           { return len(p) }
func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
