// Copyright 2020 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 godoc

import (
	"context"
	"errors"
	"fmt"
	"go/ast"
	"path"
	"sort"
	"strings"

	"github.com/google/safehtml/template"
	"golang.org/x/mod/semver"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/godoc/dochtml"
	"golang.org/x/pkgsite/internal/godoc/internal/doc"
	"golang.org/x/pkgsite/internal/source"
	"golang.org/x/pkgsite/internal/stdlib"
)

const (
	megabyte             = 1000 * 1000
	maxImportsPerPackage = 2000

	// Exported for tests.
	DocTooLargeReplacement = `<p>Documentation is too large to display.</p>`
)

// MaxDocumentationHTML is a limit on the rendered documentation HTML size.
//
// The current limit of is based on the largest packages that
// pkg.go.dev has encountered. See https://golang.org/issue/40576.
//
// It is a variable for testing.
var MaxDocumentationHTML = 20 * megabyte

// DocInfo returns information extracted from the package's documentation.
// This destroys p's AST; do not call any methods of p after it returns.
func (p *Package) DocInfo(ctx context.Context, innerPath string, sourceInfo *source.Info, modInfo *ModuleInfo) (
	synopsis string, imports []string, api []*internal.Symbol, err error) {
	// This is mostly copied from internal/fetch/fetch.go.
	defer derrors.Wrap(&err, "godoc.Package.DocInfo(%q, %q, %q)", modInfo.ModulePath, modInfo.ResolvedVersion, innerPath)

	p.renderCalled = true
	d, err := p.docPackage(innerPath, modInfo)
	if err != nil {
		return "", nil, nil, err
	}

	api, err = dochtml.GetSymbols(d, p.Fset)
	if err != nil {
		return "", nil, nil, err
	}
	return doc.Synopsis(d.Doc), cleanImports(d.Imports, d.ImportPath), api, nil
}

// cleanImports cleans import paths, in the sense of path.Clean.
//
// An import path consisting of a single dot is dropped. It refers
// to the package itself.
//
// Import paths with leading "." or ".." components are resolved against the
// package's own import path.
//
// Other dot components are resolved with path.Clean.
//
// Cleaning may result in duplicates, which are removed.
func cleanImports(imports []string, importPath string) []string {
	var r []string
	seen := map[string]bool{}
	for _, im := range imports {
		if im == ".." || strings.HasPrefix(im, "./") || strings.HasPrefix(im, "../") {
			im = path.Join(importPath, im)
		}
		c := path.Clean(im)
		if c != "." && !seen[c] {
			r = append(r, c)
			seen[c] = true
		}
	}
	return r
}

// docPackage computes and returns a doc.Package.
func (p *Package) docPackage(innerPath string, modInfo *ModuleInfo) (_ *doc.Package, err error) {
	defer derrors.Wrap(&err, "docPackage(%q, %q, %q)", innerPath, modInfo.ModulePath, modInfo.ResolvedVersion)
	importPath := path.Join(modInfo.ModulePath, innerPath)
	if modInfo.ModulePath == stdlib.ModulePath {
		importPath = innerPath
	}
	if modInfo.ModulePackages == nil {
		modInfo.ModulePackages = p.ModulePackagePaths
	}

	// The "builtin" package in the standard library is a special case.
	// We want to show documentation for all globals (not just exported ones),
	// and avoid association of consts, vars, and factory functions with types
	// since it's not helpful (see golang.org/issue/6645).
	var noFiltering, noTypeAssociation bool
	if modInfo.ModulePath == stdlib.ModulePath && importPath == "builtin" {
		noFiltering = true
		noTypeAssociation = true
	}

	// Compute package documentation.
	var m doc.Mode
	if noFiltering {
		m |= doc.AllDecls
	}
	var allGoFiles []*ast.File
	for _, f := range p.Files {
		allGoFiles = append(allGoFiles, f.AST)
	}
	d, err := doc.NewFromFiles(p.Fset, allGoFiles, importPath, m)
	if err != nil {
		return nil, fmt.Errorf("doc.NewFromFiles: %v", err)
	}

	if d.ImportPath != importPath {
		panic(fmt.Errorf("internal error: *doc.Package has an unexpected import path (%q != %q)", d.ImportPath, importPath))
	}
	if noTypeAssociation {
		for _, t := range d.Types {
			d.Consts, t.Consts = append(d.Consts, t.Consts...), nil
			d.Vars, t.Vars = append(d.Vars, t.Vars...), nil
			d.Funcs, t.Funcs = append(d.Funcs, t.Funcs...), nil
		}
		sort.Slice(d.Funcs, func(i, j int) bool { return d.Funcs[i].Name < d.Funcs[j].Name })
	}

	// Process package imports.
	if len(d.Imports) > maxImportsPerPackage {
		return nil, fmt.Errorf("%d imports found package %q; exceeds limit %d for maxImportsPerPackage", len(d.Imports), importPath, maxImportsPerPackage)
	}
	return d, nil
}

// renderOptions returns a RenderOptions for p.
func (p *Package) renderOptions(innerPath string, sourceInfo *source.Info, modInfo *ModuleInfo,
	nameToVersion map[string]string) dochtml.RenderOptions {
	sourceLinkFunc := func(n ast.Node) string {
		if sourceInfo == nil {
			return ""
		}
		p := p.Fset.Position(n.Pos())
		if p.Line == 0 { // invalid Position
			return ""
		}
		return sourceInfo.LineURL(path.Join(innerPath, p.Filename), p.Line)
	}
	fileLinkFunc := func(filename string) string {
		if sourceInfo == nil {
			return ""
		}
		return sourceInfo.FileURL(path.Join(innerPath, filename))
	}

	return dochtml.RenderOptions{
		FileLinkFunc:     fileLinkFunc,
		SourceLinkFunc:   sourceLinkFunc,
		ModInfo:          modInfo,
		SinceVersionFunc: sinceVersionFunc(modInfo.ModulePath, nameToVersion),
		Limit:            int64(MaxDocumentationHTML),
	}
}

// sinceVersionFunc returns a func that reports the version when the symbol
// with name was first introduced.  nameToVersion is a map of symbol name to
// the first version that symbol name was seen in the package.
//
// If the version when the symbol name was first introduced is the earliest
// version in nameToVersion, an empty string is returned. This is because we
// don't want to display that information on the main page to reduce clutter.
func sinceVersionFunc(modulePath string, nameToVersion map[string]string) func(name string) string {
	if nameToVersion == nil {
		return func(string) string {
			return ""
		}
	}

	var earliest string
	for _, v := range nameToVersion {
		if earliest == "" {
			earliest = v
			continue
		}
		if semver.Compare(v, earliest) < 0 {
			earliest = v
		}
	}

	return func(name string) string {
		if nameToVersion == nil {
			return ""
		}
		v := nameToVersion[name]
		if v == earliest {
			return ""
		}
		if modulePath == stdlib.ModulePath {
			// This should never return an error.
			tag, _ := stdlib.TagForVersion(v)
			return tag
		}
		return v
	}
}

// Render renders the documentation for the package.
// Rendering destroys p's AST; do not call any methods of p after it returns.
func (p *Package) Render(ctx context.Context, innerPath string,
	sourceInfo *source.Info, modInfo *ModuleInfo, nameToVersion map[string]string) (_ *dochtml.Parts, err error) {
	p.renderCalled = true

	d, err := p.docPackage(innerPath, modInfo)
	if err != nil {
		return nil, err
	}

	opts := p.renderOptions(innerPath, sourceInfo, modInfo, nameToVersion)
	parts, err := dochtml.Render(ctx, p.Fset, d, opts)
	if errors.Is(err, ErrTooLarge) {
		return &dochtml.Parts{Body: template.MustParseAndExecuteToHTML(DocTooLargeReplacement)}, nil
	}
	if err != nil {
		return nil, fmt.Errorf("dochtml.Render: %v", err)
	}
	return parts, nil
}

// RenderFromUnit is a convenience function that first decodes the source
// in the unit, which must exist, and then calls Render.
func RenderFromUnit(ctx context.Context, u *internal.Unit) (_ *dochtml.Parts, err error) {
	docPkg, err := DecodePackage(u.Documentation[0].Source)
	if err != nil {
		return nil, err
	}
	modInfo := &ModuleInfo{
		ModulePath:      u.ModulePath,
		ResolvedVersion: u.Version,
		ModulePackages:  nil, // will be provided by docPkg
	}
	var innerPath string
	if u.ModulePath == stdlib.ModulePath {
		innerPath = u.Path
	} else if u.Path != u.ModulePath {
		innerPath = u.Path[len(u.ModulePath)+1:]
	}
	return docPkg.Render(ctx, innerPath, u.SourceInfo, modInfo, nil)
}
