// 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 dochtml renders Go package documentation into HTML.
//
// This package and its API are under development (see golang.org/issue/39883).
// The plan is to iterate on the development internally for x/pkgsite
// needs first, before factoring it out somewhere non-internal where its
// API can no longer be easily modified.
package dochtml

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"go/ast"
	"go/doc"
	"go/printer"
	"go/token"
	"sort"
	"strings"

	"github.com/google/safehtml"
	"github.com/google/safehtml/legacyconversions"
	"github.com/google/safehtml/template"
	"github.com/google/safehtml/uncheckedconversions"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/godoc/dochtml/internal/render"
	"golang.org/x/text/cases"
	"golang.org/x/text/language"
)

var (
	// ErrTooLarge represents an error where the rendered documentation HTML
	// size exceeded the specified limit. See the RenderOptions.Limit field.
	ErrTooLarge = errors.New("rendered documentation HTML size exceeded the specified limit")
)

// ModuleInfo contains all the information a package needs about the module it
// belongs to in order to render its documentation.
type ModuleInfo struct {
	ModulePath      string
	ResolvedVersion string
	// ModulePackages is the set of all full package paths in the module.
	ModulePackages map[string]bool
}

// RenderOptions are options for Render.
type RenderOptions struct {
	// FileLinkFunc optionally specifies a function that
	// returns a URL where file should be linked to.
	// file is the name component of a .go file in the package,
	// including the .go qualifier.
	// As a special case, FileLinkFunc may return the empty
	// string to indicate that a given file should not be linked.
	FileLinkFunc     func(file string) (url string)
	SourceLinkFunc   func(ast.Node) string
	SinceVersionFunc func(name string) string
	// ModInfo optionally specifies information about the module the package
	// belongs to in order to render module-related documentation.
	ModInfo      *ModuleInfo
	Limit        int64 // If zero, a default limit of 10 megabytes is used.
	BuildContext internal.BuildContext
}

// templateData holds the data passed to the HTML templates in this package.
type templateData struct {
	RootURL                    string
	Package                    *doc.Package
	Consts, Vars, Funcs, Types []*item
	Examples                   *examples
	NoteHeaders                map[string]noteHeader
}

// Parts contains HTML for each part of the documentation.
type Parts struct {
	Body          safehtml.HTML // main body of doc
	Outline       safehtml.HTML // outline for large screens
	MobileOutline safehtml.HTML // outline for mobile
	Links         []render.Link // "Links" section of package doc
}

// Render renders package documentation HTML for the
// provided file set and package, in separate parts.
//
// If any of the rendered documentation part HTML sizes exceeds the specified limit,
// an error with ErrTooLarge in its chain will be returned.
func Render(ctx context.Context, fset *token.FileSet, p *doc.Package, opt RenderOptions) (_ *Parts, err error) {
	defer derrors.Wrap(&err, "dochtml.RenderParts")

	if opt.Limit == 0 {
		const megabyte = 1000 * 1000
		opt.Limit = 10 * megabyte
	}

	funcs, data, links := renderInfo(ctx, fset, p, opt)
	p = data.Package
	if docIsEmpty(p) {
		return &Parts{}, nil
	}

	exec := func(tmpl *template.Template) safehtml.HTML {
		if err != nil {
			return safehtml.HTML{}
		}
		t := template.Must(tmpl.Clone()).Funcs(funcs)
		var html safehtml.HTML
		html, err = executeToHTMLWithLimit(t, data, opt.Limit)
		return html
	}

	parts := &Parts{
		Body:          exec(bodyTemplate),
		Outline:       exec(outlineTemplate),
		MobileOutline: exec(sidenavTemplate),
		// links must be called after body, because the call to
		// render_doc_extract_links in body.tmpl creates the links.
		Links: links(),
	}
	if err != nil {
		return nil, err
	}
	return parts, nil
}

// An item is rendered as one piece of documentation. It is essentially a union
// of the Value, Type and Func types from internal/doc, along with additional
// information for HTML rendering, like class names.
type item struct {
	Doc                          string
	Decl                         ast.Decl   // GenDecl for consts, vars and types; FuncDecl for functions
	Name                         string     // for types and functions; empty for consts and vars
	FullName                     string     // for methods, the type name + "." + Name; else same as Name
	HeaderStart                  string     // text of header, before source link
	Examples                     []*example // for types and functions; empty for vars and consts
	IsDeprecated                 bool
	Consts, Vars, Funcs, Methods []*item // for types
	// HTML-specific values, for types and functions
	Kind        string // for data-kind attribute
	HeaderClass string // class for header
}

func packageToItems(p *doc.Package, exmap map[string][]*example) (consts, vars, funcs, types []*item) {
	consts = valuesToItems(p.Consts)
	vars = valuesToItems(p.Vars)
	funcs = funcsToItems(p.Funcs, "Documentation-functionHeader", "", exmap)
	for _, t := range p.Types {
		types = append(types, typeToItem(t, exmap))
	}
	return consts, vars, funcs, types
}

func valuesToItems(vs []*doc.Value) []*item {
	var r []*item
	for _, v := range vs {
		r = append(r, valueToItem(v))
	}
	return r
}

func valueToItem(v *doc.Value) *item {
	return &item{
		Doc:          v.Doc,
		Decl:         v.Decl,
		IsDeprecated: valueIsDeprecated(v),
	}
}

func funcsToItems(fs []*doc.Func, hclass, typeName string, exmap map[string][]*example) []*item {
	var r []*item
	for _, f := range fs {
		fullName := f.Name
		if typeName != "" {
			fullName = typeName + "." + f.Name
		}
		kind := "function"
		headerStart := "func"
		if f.Recv != "" {
			kind = "method"
			headerStart += " (" + f.Recv + ")"
		}
		i := &item{
			Doc:          f.Doc,
			Decl:         f.Decl,
			Name:         f.Name,
			FullName:     fullName,
			HeaderStart:  headerStart,
			IsDeprecated: funcIsDeprecated(f),
			Examples:     exmap[fullName],
			Kind:         kind,
			HeaderClass:  hclass,
		}
		r = append(r, i)
	}
	return r
}

func typeToItem(t *doc.Type, exmap map[string][]*example) *item {
	return &item{
		Name:         t.Name,
		FullName:     t.Name,
		Doc:          t.Doc,
		Decl:         t.Decl,
		HeaderStart:  "type",
		IsDeprecated: typeIsDeprecated(t),
		Kind:         "type",
		HeaderClass:  "Documentation-typeHeader",
		Examples:     exmap[t.Name],
		Consts:       valuesToItems(t.Consts),
		Vars:         valuesToItems(t.Vars),
		Funcs:        funcsToItems(t.Funcs, "Documentation-typeFuncHeader", "", exmap),
		Methods:      funcsToItems(t.Methods, "Documentation-typeMethodHeader", t.Name, exmap),
	}
}

func docIsEmpty(p *doc.Package) bool {
	return p.Doc == "" &&
		len(p.Examples) == 0 &&
		len(p.Consts) == 0 &&
		len(p.Vars) == 0 &&
		len(p.Types) == 0 &&
		len(p.Funcs) == 0
}

// renderInfo returns the functions and data needed to render the doc.
func renderInfo(ctx context.Context, fset *token.FileSet, p *doc.Package, opt RenderOptions) (map[string]any, templateData, func() []render.Link) {
	// Make a copy to avoid modifying caller's *doc.Package.
	p2 := *p
	p = &p2

	// When rendering documentation for commands, display
	// the package comment and notes, but no declarations.
	if p.Name == "main" {
		// Clear top-level declarations.
		p.Consts = nil
		p.Types = nil
		p.Vars = nil
		p.Funcs = nil
		p.Examples = nil
	}

	// Remove everything from the notes section that is not a bug. This
	// includes TODOs and other arbitrary notes.
	for k := range p.Notes {
		if k == "BUG" {
			continue
		}
		delete(p.Notes, k)
	}

	r := render.New(ctx, fset, p, &render.Options{
		PackageURL: func(path string) string {
			// Use the same module version for imported packages that belong to
			// the same module.
			versionedPath := path
			if opt.ModInfo != nil {
				versionedPath = versionedPkgPath(path, opt.ModInfo)
			}
			var search string
			if opt.BuildContext.GOOS != "" && opt.BuildContext.GOOS != "all" {
				search = "?GOOS=" + opt.BuildContext.GOOS
			}
			return "/" + versionedPath + search
		},
	})

	fileLink := func(name string) safehtml.HTML {
		return linkHTML(name, opt.FileLinkFunc(name), "Documentation-file")
	}
	sourceLink := func(name string, node ast.Node) safehtml.HTML {
		return linkHTML(name, opt.SourceLinkFunc(node), "Documentation-source")
	}
	sinceVersion := func(name string) safehtml.HTML {
		return safehtml.HTMLEscaped(opt.SinceVersionFunc(name))
	}
	funcs := map[string]any{
		"render_short_synopsis":    r.ShortSynopsis,
		"render_synopsis":          r.Synopsis,
		"render_doc":               r.DocHTML,
		"render_doc_extract_links": r.DocHTMLExtractLinks,
		"render_decl":              r.DeclHTML,
		"render_code":              r.CodeHTML,
		"file_link":                fileLink,
		"source_link":              sourceLink,
		"since_version":            sinceVersion,
	}
	examples := collectExamples(p)
	data := templateData{
		Package:     p,
		RootURL:     "/pkg",
		Examples:    examples,
		NoteHeaders: buildNoteHeaders(p.Notes),
	}
	data.Consts, data.Vars, data.Funcs, data.Types = packageToItems(p, examples.Map)
	return funcs, data, r.Links
}

// executeToHTMLWithLimit executes tmpl on data and returns the result as a safehtml.HTML.
// It returns an error if the size of the result exceeds limit.
func executeToHTMLWithLimit(tmpl *template.Template, data any, limit int64) (safehtml.HTML, error) {
	buf := &limitBuffer{B: new(bytes.Buffer), Remain: limit}
	err := tmpl.Execute(buf, data)
	if buf.Remain < 0 {
		return safehtml.HTML{}, fmt.Errorf("dochtml.Render: %w", ErrTooLarge)
	} else if err != nil {
		return safehtml.HTML{}, fmt.Errorf("dochtml.Render: %v", err)
	}

	// This is safe because we're executing a safehtml template and not modifying the result afterwards.
	// We're just doing what safehtml/template.Template.ExecuteToHTML does
	// (https://github.com/google/safehtml/blob/b8ae3e5e1ce3/template/template.go#L136).
	return uncheckedconversions.HTMLFromStringKnownToSatisfyTypeContract(buf.B.String()), nil
}

// linkHTML returns an HTML-formatted name linked to the given URL.
// The class argument is the class of the 'a' tag.
// If url is the empty string, the name is not linked.
func linkHTML(name, url, class string) safehtml.HTML {
	if url == "" {
		return safehtml.HTMLEscaped(name)
	}
	return render.ExecuteToHTML(render.LinkTemplate, render.Link{Class: class, Href: url, Text: name})
}

// examples is an internal representation of all package examples.
type examples struct {
	List []*example            // sorted by ParentID
	Map  map[string][]*example // keyed by top-level ID (e.g., "NewRing" or "PubSub.Receive") or empty string for package examples
}

// example is an internal representation of a single example.
type example struct {
	*doc.Example
	ID       safehtml.Identifier // ID of example
	ParentID string              // ID of top-level declaration this example is attached to
	Suffix   string              // optional suffix name in title case
}

// Code returns an printer.CommentedNode if ex.Comments is non-nil,
// otherwise it returns ex.Code as is.
func (ex *example) Code() any {
	if len(ex.Comments) > 0 {
		return &printer.CommentedNode{Node: ex.Example.Code, Comments: ex.Comments}
	}
	return ex.Example.Code
}

// WalkExamples calls fn for each Example in p,
// setting id to the name of the parent structure.
func WalkExamples(p *doc.Package, fn func(id string, ex *doc.Example)) {
	for _, ex := range p.Examples {
		fn("", ex)
	}
	for _, f := range p.Funcs {
		for _, ex := range f.Examples {
			fn(f.Name, ex)
		}
	}
	for _, t := range p.Types {
		for _, ex := range t.Examples {
			fn(t.Name, ex)
		}
		for _, f := range t.Funcs {
			for _, ex := range f.Examples {
				fn(f.Name, ex)
			}
		}
		for _, m := range t.Methods {
			for _, ex := range m.Examples {
				fn(t.Name+"."+m.Name, ex)
			}
		}
	}
}

// collectExamples extracts examples from p
// into the internal examples representation.
func collectExamples(p *doc.Package) *examples {
	exs := &examples{
		List: nil,
		Map:  make(map[string][]*example),
	}
	WalkExamples(p, func(id string, ex *doc.Example) {
		suffix := cases.Title(language.English, cases.NoLower).String(ex.Suffix)
		ex0 := &example{
			Example:  ex,
			ID:       exampleID(id, suffix),
			ParentID: id,
			Suffix:   suffix,
		}
		exs.List = append(exs.List, ex0)
		exs.Map[id] = append(exs.Map[id], ex0)
	})
	sort.SliceStable(exs.List, func(i, j int) bool {
		// TODO: Break ties by sorting by suffix, unless
		// not needed because of upstream slice order.
		return exs.List[i].ParentID < exs.List[j].ParentID
	})
	return exs
}

func exampleID(id, suffix string) safehtml.Identifier {
	switch {
	case id == "" && suffix == "":
		return safehtml.IdentifierFromConstant("example-package")
	case id == "" && suffix != "":
		render.ValidateGoDottedExpr(suffix)
		return legacyconversions.RiskilyAssumeIdentifier("example-package-" + suffix)
	case id != "" && suffix == "":
		render.ValidateGoDottedExpr(id)
		return legacyconversions.RiskilyAssumeIdentifier("example-" + id)
	case id != "" && suffix != "":
		render.ValidateGoDottedExpr(id)
		render.ValidateGoDottedExpr(suffix)
		return legacyconversions.RiskilyAssumeIdentifier("example-" + id + "-" + suffix)
	default:
		panic("unreachable")
	}
}

// noteHeader contains information the template needs to render
// the note related HTML tags in documentation page.
type noteHeader struct {
	SafeIdentifier safehtml.Identifier
	Label          string
}

// buildNoteHeaders constructs note headers from note markers.
// It returns a map from each marker to its corresponding noteHeader.
func buildNoteHeaders(notes map[string][]*doc.Note) map[string]noteHeader {
	headers := map[string]noteHeader{}
	for marker := range notes {
		headers[marker] = noteHeader{
			SafeIdentifier: safehtml.IdentifierFromConstantPrefix("pkg-note", marker),
			Label:          cases.Title(language.Und).String(strings.ToLower(marker)),
		}
	}
	return headers
}

// versionedPkgPath transforms package paths to contain the same version as the
// current module if the package belongs to the module. As a special case,
// versionedPkgPath will not add versions to standard library packages.
func versionedPkgPath(pkgPath string, modInfo *ModuleInfo) string {
	if modInfo == nil || !modInfo.ModulePackages[pkgPath] {
		return pkgPath
	}
	// We don't need to do anything special here for standard library packages
	// since pkgPath will never contain the "std/" module prefix, and
	// modInfo.ModulePackages contains this prefix for standard library packages.
	innerPkgPath := pkgPath[len(modInfo.ModulePath):]
	return fmt.Sprintf("%s@%s%s", modInfo.ModulePath, modInfo.ResolvedVersion, innerPkgPath)
}
