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

package source

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

	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/lsp/protocol"
	errors "golang.org/x/xerrors"
)

func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.DocumentSymbol, error) {
	ctx, done := event.Start(ctx, "source.DocumentSymbols")
	defer done()

	pkg, pgf, err := getParsedFile(ctx, snapshot, fh, NarrowestPackage)
	if err != nil {
		return nil, errors.Errorf("getting file for DocumentSymbols: %w", err)
	}

	info := pkg.GetTypesInfo()
	q := qualifier(pgf.File, pkg.GetTypes(), info)

	symbolsToReceiver := make(map[types.Type]int)
	var symbols []protocol.DocumentSymbol
	for _, decl := range pgf.File.Decls {
		switch decl := decl.(type) {
		case *ast.FuncDecl:
			if obj := info.ObjectOf(decl.Name); obj != nil {
				fs, err := funcSymbol(snapshot, pkg, decl, obj, q)
				if err != nil {
					return nil, err
				}
				// If function is a method, prepend the type of the method.
				if fs.Kind == protocol.Method {
					rtype := obj.Type().(*types.Signature).Recv().Type()
					fs.Name = fmt.Sprintf("(%s).%s", types.TypeString(rtype, q), fs.Name)
				}
				symbols = append(symbols, fs)
			}
		case *ast.GenDecl:
			for _, spec := range decl.Specs {
				switch spec := spec.(type) {
				case *ast.TypeSpec:
					if obj := info.ObjectOf(spec.Name); obj != nil {
						ts, err := typeSymbol(snapshot, pkg, info, spec, obj, q)
						if err != nil {
							return nil, err
						}
						symbols = append(symbols, ts)
						symbolsToReceiver[obj.Type()] = len(symbols) - 1
					}
				case *ast.ValueSpec:
					for _, name := range spec.Names {
						if obj := info.ObjectOf(name); obj != nil {
							vs, err := varSymbol(snapshot, pkg, decl, name, obj, q)
							if err != nil {
								return nil, err
							}
							symbols = append(symbols, vs)
						}
					}
				}
			}
		}
	}
	return symbols, nil
}

func funcSymbol(snapshot Snapshot, pkg Package, decl *ast.FuncDecl, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Function,
	}
	var err error
	s.Range, err = nodeToProtocolRange(snapshot, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, decl.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	sig, _ := obj.Type().(*types.Signature)
	if sig != nil {
		if sig.Recv() != nil {
			s.Kind = protocol.Method
		}
		s.Detail += "("
		for i := 0; i < sig.Params().Len(); i++ {
			if i > 0 {
				s.Detail += ", "
			}
			param := sig.Params().At(i)
			label := types.TypeString(param.Type(), q)
			if param.Name() != "" {
				label = fmt.Sprintf("%s %s", param.Name(), label)
			}
			s.Detail += label
		}
		s.Detail += ")"
	}
	return s, nil
}

func typeSymbol(snapshot Snapshot, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, qf types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
	}
	s.Detail, _ = formatType(obj.Type(), qf)
	s.Kind = typeToKind(obj.Type())

	var err error
	s.Range, err = nodeToProtocolRange(snapshot, pkg, spec)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, spec.Name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	t, objIsStruct := obj.Type().Underlying().(*types.Struct)
	st, specIsStruct := spec.Type.(*ast.StructType)
	if objIsStruct && specIsStruct {
		for i := 0; i < t.NumFields(); i++ {
			f := t.Field(i)
			child := protocol.DocumentSymbol{
				Name: f.Name(),
				Kind: protocol.Field,
			}
			child.Detail, _ = formatType(f.Type(), qf)

			spanNode, selectionNode := nodesForStructField(i, st)
			if span, err := nodeToProtocolRange(snapshot, pkg, spanNode); err == nil {
				child.Range = span
			}
			if span, err := nodeToProtocolRange(snapshot, pkg, selectionNode); err == nil {
				child.SelectionRange = span
			}
			s.Children = append(s.Children, child)
		}
	}

	ti, objIsInterface := obj.Type().Underlying().(*types.Interface)
	ai, specIsInterface := spec.Type.(*ast.InterfaceType)
	if objIsInterface && specIsInterface {
		for i := 0; i < ti.NumExplicitMethods(); i++ {
			method := ti.ExplicitMethod(i)
			child := protocol.DocumentSymbol{
				Name: method.Name(),
				Kind: protocol.Method,
			}

			var spanNode, selectionNode ast.Node
		Methods:
			for _, f := range ai.Methods.List {
				for _, id := range f.Names {
					if id.Name == method.Name() {
						spanNode, selectionNode = f, id
						break Methods
					}
				}
			}
			child.Range, err = nodeToProtocolRange(snapshot, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}

		for i := 0; i < ti.NumEmbeddeds(); i++ {
			embedded := ti.EmbeddedType(i)
			nt, isNamed := embedded.(*types.Named)
			if !isNamed {
				continue
			}

			child := protocol.DocumentSymbol{
				Name: types.TypeString(embedded, qf),
			}
			child.Kind = typeToKind(embedded)
			var spanNode, selectionNode ast.Node
		Embeddeds:
			for _, f := range ai.Methods.List {
				if len(f.Names) > 0 {
					continue
				}

				if t := info.TypeOf(f.Type); types.Identical(nt, t) {
					spanNode, selectionNode = f, f.Type
					break Embeddeds
				}
			}
			child.Range, err = nodeToProtocolRange(snapshot, pkg, spanNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			child.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, selectionNode)
			if err != nil {
				return protocol.DocumentSymbol{}, err
			}
			s.Children = append(s.Children, child)
		}
	}
	return s, nil
}

func nodesForStructField(i int, st *ast.StructType) (span, selection ast.Node) {
	j := 0
	for _, field := range st.Fields.List {
		if len(field.Names) == 0 {
			if i == j {
				return field, field.Type
			}
			j++
			continue
		}
		for _, name := range field.Names {
			if i == j {
				return field, name
			}
			j++
		}
	}
	return nil, nil
}

func varSymbol(snapshot Snapshot, pkg Package, decl ast.Node, name *ast.Ident, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
	s := protocol.DocumentSymbol{
		Name: obj.Name(),
		Kind: protocol.Variable,
	}
	if _, ok := obj.(*types.Const); ok {
		s.Kind = protocol.Constant
	}
	var err error
	s.Range, err = nodeToProtocolRange(snapshot, pkg, decl)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, name)
	if err != nil {
		return protocol.DocumentSymbol{}, err
	}
	s.Detail = types.TypeString(obj.Type(), q)
	return s, nil
}
