// Copyright 2024 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 golang

// This file implements the "Show free symbols" code action.

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
	"html"
	"sort"
	"strings"

	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/cache/parsego"
	"golang.org/x/tools/gopls/internal/util/maps"
	"golang.org/x/tools/gopls/internal/util/safetoken"
	"golang.org/x/tools/gopls/internal/util/slices"
)

// FreeSymbolsHTML returns an HTML document containing the report of
// free symbols referenced by the selection.
func FreeSymbolsHTML(viewID string, pkg *cache.Package, pgf *parsego.File, start, end token.Pos, web Web) []byte {

	// Compute free references.
	refs := freeRefs(pkg.Types(), pkg.TypesInfo(), pgf.File, start, end)

	// -- model --

	type Import struct {
		Path    metadata.PackagePath
		Symbols []string
	}
	type Symbol struct {
		Kind string
		Type string
		Refs []types.Object
	}
	var model struct {
		Imported []Import
		PkgLevel []Symbol
		Local    []Symbol
	}

	// TODO(adonovan): factor with RenderPackageDoc.
	qualifier := func(other *types.Package) string {
		// (like types.RelativeTo but using Package.Name)
		if other == pkg.Types() {
			return "" // same package; unqualified
		}
		return other.Name()
	}

	// Populate model.
	{
		// List the refs in order of dotted paths.
		sort.Slice(refs, func(i, j int) bool {
			return refs[i].dotted < refs[j].dotted
		})

		// Inspect the references.
		imported := make(map[string][]*freeRef) // refs to imported symbols, by package path
		seen := make(map[string]bool)           // to de-dup dotted paths
		for _, ref := range refs {
			if seen[ref.dotted] {
				continue // de-dup
			}
			seen[ref.dotted] = true

			var symbols *[]Symbol
			switch ref.scope {
			case "file":
				// imported symbol: group by package
				if pkgname, ok := ref.objects[0].(*types.PkgName); ok {
					path := pkgname.Imported().Path()
					imported[path] = append(imported[path], ref)
				}
				continue
			case "pkg":
				symbols = &model.PkgLevel
			case "local":
				symbols = &model.Local
			default:
				panic(ref.scope)
			}

			// Package and local symbols are presented the same way.
			// We treat each dotted path x.y.z as a separate entity.

			// Compute kind and type of last object (y in obj.x.y).
			typestr := " " + types.TypeString(ref.typ, qualifier)
			var kind string
			switch obj := ref.objects[len(ref.objects)-1].(type) {
			case *types.Var:
				kind = "var"
			case *types.Func:
				kind = "func"
			case *types.TypeName:
				if is[*types.TypeParam](obj.Type()) {
					kind = "type parameter"
				} else {
					kind = "type"
				}
				typestr = "" // avoid "type T T"
			case *types.Const:
				kind = "const"
			case *types.Label:
				kind = "label"
				typestr = "" // avoid "label L L"
			}

			*symbols = append(*symbols, Symbol{
				Kind: kind,
				Type: typestr,
				Refs: ref.objects,
			})
		}

		// Imported symbols.
		// Produce one record per package, with a list of symbols.
		pkgPaths := maps.Keys(imported)
		sort.Strings(pkgPaths)
		for _, pkgPath := range pkgPaths {
			refs := imported[pkgPath]

			var syms []string
			for _, ref := range refs {
				// strip package name (bytes.Buffer.Len -> Buffer.Len)
				syms = append(syms, ref.dotted[len(ref.objects[0].Name())+len("."):])
			}
			sort.Strings(syms)
			const max = 4
			if len(syms) > max {
				syms[max-1] = fmt.Sprintf("... (%d)", len(syms))
				syms = syms[:max]
			}

			model.Imported = append(model.Imported, Import{
				Path:    PackagePath(pkgPath),
				Symbols: syms,
			})
		}
	}

	// -- presentation --

	var buf bytes.Buffer
	buf.WriteString(`<!DOCTYPE html>
<html>
<head>
<style>
.col-pkg { color: #2eb007 }
.col-file { color: #a10b15 }
.col-local { color: #0cb7c9 }
li { font-family: monospace; }
p { max-width: 6in; }
</style>
  <script src="/assets/common.js"></script>
  <link rel="stylesheet" href="/assets/common.css">
</head>
<body>
<h1>Free symbols</h1>
<p>
  The selected code contains references to these free* symbols:
</p>
`)

	// Present the refs in three sections: imported, same package, local.

	// -- imported symbols --

	// Show one item per package, with a list of symbols.
	fmt.Fprintf(&buf, "<h2><span class='col-file'>⬤</span> Imported symbols</h2>\n")
	fmt.Fprintf(&buf, "<ul>\n")
	for _, imp := range model.Imported {
		fmt.Fprintf(&buf, "<li>import \"<a href='%s'>%s</a>\" // for %s</li>\n",
			web.PkgURL(viewID, imp.Path, ""),
			html.EscapeString(string(imp.Path)),
			strings.Join(imp.Symbols, ", "))
	}
	if len(model.Imported) == 0 {
		fmt.Fprintf(&buf, "<li>(none)</li>\n")
	}
	buf.WriteString("</ul>\n")

	// -- package and local symbols --

	showSymbols := func(scope, title string, symbols []Symbol) {
		fmt.Fprintf(&buf, "<h2><span class='col-%s'>⬤</span> %s</h2>\n", scope, title)
		fmt.Fprintf(&buf, "<ul>\n")
		pre := buf.Len()
		for _, sym := range symbols {
			fmt.Fprintf(&buf, "<li>%s ", sym.Kind) // of rightmost symbol in dotted path
			for i, obj := range sym.Refs {
				if i > 0 {
					buf.WriteByte('.')
				}
				buf.WriteString(objHTML(pkg.FileSet(), web, obj))
			}
			fmt.Fprintf(&buf, " %s</li>\n", html.EscapeString(sym.Type))
		}
		if buf.Len() == pre {
			fmt.Fprintf(&buf, "<li>(none)</li>\n")
		}
		buf.WriteString("</ul>\n")
	}
	showSymbols("pkg", "Package-level symbols", model.PkgLevel)
	showSymbols("local", "Local symbols", model.Local)

	// -- code selection --

	// Print the selection, highlighting references to free symbols.
	buf.WriteString("<hr/>\n")
	sort.Slice(refs, func(i, j int) bool {
		return refs[i].expr.Pos() < refs[j].expr.Pos()
	})
	pos := start
	emitTo := func(end token.Pos) {
		if pos < end {
			fileStart := pgf.Tok.Pos(0) // TODO(adonovan): use go1.20 pgf.File.FileStart
			text := pgf.Mapper.Content[pos-fileStart : end-fileStart]
			buf.WriteString(html.EscapeString(string(text)))
			pos = end
		}
	}
	buf.WriteString(`<pre>`)
	for _, ref := range refs {
		emitTo(ref.expr.Pos())
		fmt.Fprintf(&buf, `<b class='col-%s'>`, ref.scope)
		emitTo(ref.expr.End())
		buf.WriteString(`</b>`)
	}
	emitTo(end)
	buf.WriteString(`</pre>
<hr>
<p>
  *A symbol is "free" if it is referenced within the selection but declared
  outside of it.

  The free variables are approximately the set of parameters that
  would be needed if the block were extracted into its own function in
  the same package.

  Free identifiers may include local types and control labels as well.

  Even when you don't intend to extract a block into a new function,
  this information can help you to tell at a glance what names a block
  of code depends on.
</p>
<p>
  Each dotted path of identifiers (such as file.Name.Pos) is reported
  as a separate item, so that you can see which parts of a complex
  type are actually needed.

  Viewing the free symbols referenced by the body of a function may
  reveal that only a small part (a single field of a struct, say) of
  one of the function's parameters is used, allowing you to simplify
  and generalize the function by choosing a different type for that
  parameter.
</p>
`)
	return buf.Bytes()
}

// A freeRef records a reference to a dotted path obj.x.y,
// where obj (=objects[0]) is a free symbol.
type freeRef struct {
	objects []types.Object // [obj x y]
	dotted  string         // "obj.x.y"  (used as sort key)
	scope   string         // scope of obj: pkg|file|local
	expr    ast.Expr       // =*Ident|*SelectorExpr
	typ     types.Type     // type of obj.x.y
}

// freeRefs returns the list of references to free symbols (from
// within the selection to a symbol declared outside of it).
// It uses only info.{Scopes,Types,Uses}.
func freeRefs(pkg *types.Package, info *types.Info, file *ast.File, start, end token.Pos) []*freeRef {
	// Keep us honest about which fields we access.
	info = &types.Info{
		Scopes: info.Scopes,
		Types:  info.Types,
		Uses:   info.Uses,
	}

	fileScope := info.Scopes[file]
	pkgScope := fileScope.Parent()

	// id is called for the leftmost id x in each dotted chain such as (x.y).z.
	// suffix is the reversed suffix of selections (e.g. [z y]).
	id := func(n *ast.Ident, suffix []types.Object) *freeRef {
		obj := info.Uses[n]
		if obj == nil {
			return nil // not a reference
		}
		if start <= obj.Pos() && obj.Pos() < end {
			return nil // defined within selection => not free
		}
		parent := obj.Parent()

		// Compute dotted path.
		objects := append(suffix, obj)
		if obj.Pkg() != nil && obj.Pkg() != pkg && isPackageLevel(obj) { // dot import
			// Synthesize the implicit PkgName.
			pkgName := types.NewPkgName(token.NoPos, pkg, obj.Pkg().Name(), obj.Pkg())
			parent = fileScope
			objects = append(objects, pkgName)
		}
		slices.Reverse(objects)
		var dotted strings.Builder
		for i, obj := range objects {
			if obj == nil {
				return nil // type error
			}
			if i > 0 {
				dotted.WriteByte('.')
			}
			dotted.WriteString(obj.Name())
		}

		// Compute scope of base object.
		var scope string
		switch parent {
		case nil:
			return nil // interface method or struct field
		case types.Universe:
			return nil // built-in (not interesting)
		case fileScope:
			scope = "file" // defined at file scope (imported package)
		case pkgScope:
			scope = "pkg" // defined at package level
		default:
			scope = "local" // defined within current function
		}

		return &freeRef{
			objects: objects,
			dotted:  dotted.String(),
			scope:   scope,
		}
	}

	// sel(x.y.z, []) calls sel(x.y, [z]) calls id(x, [z, y]).
	sel := func(sel *ast.SelectorExpr, suffix []types.Object) *freeRef {
		for {
			suffix = append(suffix, info.Uses[sel.Sel])

			switch x := astutil.Unparen(sel.X).(type) {
			case *ast.Ident:
				return id(x, suffix)
			default:
				return nil
			case *ast.SelectorExpr:
				sel = x
			}
		}
	}

	// Visit all the identifiers in the selected ASTs.
	var free []*freeRef
	path, _ := astutil.PathEnclosingInterval(file, start, end)
	var visit func(n ast.Node) bool
	visit = func(n ast.Node) bool {
		// Is this node contained within the selection?
		// (freesymbols permits inexact selections,
		// like two stmts in a block.)
		if n != nil && start <= n.Pos() && n.End() <= end {
			var ref *freeRef
			switch n := n.(type) {
			case *ast.Ident:
				ref = id(n, nil)
			case *ast.SelectorExpr:
				ref = sel(n, nil)
			}

			if ref != nil {
				ref.expr = n.(ast.Expr)
				ref.typ = info.Types[n.(ast.Expr)].Type
				free = append(free, ref)
			}

			// After visiting x.sel, don't descend into sel.
			// Descend into x only if we didn't get a ref for x.sel.
			if sel, ok := n.(*ast.SelectorExpr); ok {
				if ref == nil {
					ast.Inspect(sel.X, visit)
				}
				return false
			}
		}

		return true // descend
	}
	ast.Inspect(path[0], visit)
	return free
}

// objHTML returns HTML for obj.Name(), possibly marked up as a link
// to the web server that, when visited, opens the declaration in the
// client editor.
func objHTML(fset *token.FileSet, web Web, obj types.Object) string {
	text := obj.Name()
	if posn := safetoken.StartPosition(fset, obj.Pos()); posn.IsValid() {
		url := web.SrcURL(posn.Filename, posn.Line, posn.Column)
		return sourceLink(text, url)
	}
	return text
}

// sourceLink returns HTML for a link to open a file in the client editor.
func sourceLink(text, url string) string {
	// The /src URL returns nothing but has the side effect
	// of causing the LSP client to open the requested file.
	// So we use onclick to prevent the browser from navigating.
	// We keep the href attribute as it causes the <a> to render
	// as a link: blue, underlined, with URL hover information.
	return fmt.Sprintf(`<a href="%[1]s" onclick='return httpGET("%[1]s")'>%[2]s</a>`,
		html.EscapeString(url), text)
}
