// 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/doc"
	"go/format"
	"go/token"
	"go/types"
	"strings"
)

// formatter returns the a hover value formatted with its documentation.
type formatter func(interface{}, *ast.CommentGroup) (string, error)

func (i *IdentifierInfo) Hover(ctx context.Context, qf types.Qualifier, markdownSupported, wantComments bool) (string, error) {
	file := i.File.GetAST(ctx)
	if qf == nil {
		pkg := i.File.GetPackage(ctx)
		qf = qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo())
	}
	var b strings.Builder
	f := func(x interface{}, c *ast.CommentGroup) (string, error) {
		if !wantComments {
			c = nil
		}
		return writeHover(x, i.File.GetFileSet(ctx), &b, c, markdownSupported, qf)
	}
	obj := i.Declaration.Object
	switch node := i.Declaration.Node.(type) {
	case *ast.GenDecl:
		switch obj := obj.(type) {
		case *types.TypeName, *types.Var, *types.Const, *types.Func:
			return formatGenDecl(node, obj, obj.Type(), f)
		}
	case *ast.FuncDecl:
		if _, ok := obj.(*types.Func); ok {
			return f(obj, node.Doc)
		}
	}
	return f(obj, nil)
}

func formatGenDecl(node *ast.GenDecl, obj types.Object, typ types.Type, f formatter) (string, error) {
	if _, ok := typ.(*types.Named); ok {
		switch typ.Underlying().(type) {
		case *types.Interface, *types.Struct:
			return formatGenDecl(node, obj, typ.Underlying(), f)
		}
	}
	var spec ast.Spec
	for _, s := range node.Specs {
		if s.Pos() <= obj.Pos() && obj.Pos() <= s.End() {
			spec = s
			break
		}
	}
	if spec == nil {
		return "", fmt.Errorf("no spec for node %v at position %v", node, obj.Pos())
	}
	// If we have a field or method.
	switch obj.(type) {
	case *types.Var, *types.Const, *types.Func:
		return formatVar(spec, obj, f)
	}
	// Handle types.
	switch spec := spec.(type) {
	case *ast.TypeSpec:
		if len(node.Specs) > 1 {
			// If multiple types are declared in the same block.
			return f(spec.Type, spec.Doc)
		} else {
			return f(spec, node.Doc)
		}
	case *ast.ValueSpec:
		return f(spec, spec.Doc)
	case *ast.ImportSpec:
		return f(spec, spec.Doc)
	}
	return "", fmt.Errorf("unable to format spec %v (%T)", spec, spec)
}

func formatVar(node ast.Spec, obj types.Object, f formatter) (string, error) {
	var fieldList *ast.FieldList
	if spec, ok := node.(*ast.TypeSpec); ok {
		switch t := spec.Type.(type) {
		case *ast.StructType:
			fieldList = t.Fields
		case *ast.InterfaceType:
			fieldList = t.Methods
		}
	}
	// If we have a struct or interface declaration,
	// we need to match the object to the corresponding field or method.
	if fieldList != nil {
		for i := 0; i < len(fieldList.List); i++ {
			field := fieldList.List[i]
			if field.Pos() <= obj.Pos() && obj.Pos() <= field.End() {
				if field.Doc.Text() != "" {
					return f(obj, field.Doc)
				} else if field.Comment.Text() != "" {
					return f(obj, field.Comment)
				}
			}
		}
	}
	// If we weren't able to find documentation for the object.
	return f(obj, nil)
}

// writeHover writes the hover for a given node and its documentation.
func writeHover(x interface{}, fset *token.FileSet, b *strings.Builder, c *ast.CommentGroup, markdownSupported bool, qf types.Qualifier) (string, error) {
	if c != nil {
		// TODO(rstambler): Improve conversion from Go docs to markdown.
		b.WriteString(doc.Synopsis(c.Text()))
		b.WriteRune('\n')
	}
	if markdownSupported {
		b.WriteString("```go\n")
	}
	switch x := x.(type) {
	case ast.Node:
		if err := format.Node(b, fset, x); err != nil {
			return "", err
		}
	case types.Object:
		b.WriteString(types.ObjectString(x, qf))
	}
	if markdownSupported {
		b.WriteString("\n```")
	}
	return b.String(), nil
}
