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

import (
	"context"
	"errors"

	"github.com/google/safehtml"
	"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"
	"golang.org/x/pkgsite/internal/godoc/dochtml"
	"golang.org/x/pkgsite/internal/log"
	"golang.org/x/pkgsite/internal/middleware"
	"golang.org/x/pkgsite/internal/middleware/stats"
	"golang.org/x/pkgsite/internal/version"
	"golang.org/x/text/message"
)

// MainDetails contains data needed to render the unit template.
type MainDetails struct {
	// Directories are packages and nested modules relative to the path for the
	// unit.
	Directories []*Directory

	// Licenses contains license metadata used in the header.
	Licenses []LicenseMetadata

	// NumImports is the number of imports for the package.
	NumImports string

	// CommitTime is time that this version was published, or the time that
	// has elapsed since this version was committed if it was done so recently.
	CommitTime string

	// Readme is the rendered readme HTML.
	Readme safehtml.HTML

	// ReadmeOutline is a collection of headings from the readme file
	// used to render the readme outline in the sidebar.
	ReadmeOutline []*Heading

	// ReadmeLinks are from the "Links" section of this unit's readme file, and
	// are displayed on the right sidebar.
	ReadmeLinks []link

	// DocLinks are from the "Links" section of the Go package documentation,
	// and are displayed on the right sidebar.
	DocLinks []link

	// ModuleReadmeLinks are from the "Links" section of this unit's module, if
	// the unit is not itself a module. They are displayed on the right sidebar.
	// See https://golang.org/issue/42968.
	ModuleReadmeLinks []link

	// ImportedByCount is the number of packages that import this path.
	// When the count is > limit it will read as 'limit+'. This field
	// is not supported when using a datasource proxy.
	ImportedByCount string

	DocBody       safehtml.HTML
	DocOutline    safehtml.HTML
	MobileOutline safehtml.HTML
	IsPackage     bool

	// DocSynopsis is used as the content for the <meta name="Description">
	// tag on the main unit page.
	DocSynopsis string

	// GOOS and GOARCH are the build context for the doc.
	GOOS, GOARCH string

	// BuildContexts holds the values for build contexts available for the doc.
	BuildContexts []internal.BuildContext

	// SourceFiles contains .go files for the package.
	SourceFiles []*File

	// RepositoryURL is the URL to the repository containing the package.
	RepositoryURL string

	// SourceURL is the URL to the source of the package.
	SourceURL string

	// ExpandReadme is holds the expandable readme state.
	ExpandReadme bool

	// ModFileURL is an URL to the mod file.
	ModFileURL string

	// IsTaggedVersion is true if the version is not a psuedorelease.
	IsTaggedVersion bool

	// IsStableVersion is true if the major version is v1 or greater.
	IsStableVersion bool
}

// File is a source file for a package.
type File struct {
	Name string
	URL  string
}

func fetchMainDetails(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta,
	requestedVersion string, expandReadme bool, bc internal.BuildContext) (_ *MainDetails, err error) {
	defer stats.Elapsed(ctx, "fetchMainDetails")()

	unit, err := ds.GetUnit(ctx, um, internal.WithMain, bc)
	if err != nil {
		return nil, err
	}
	subdirectories := getSubdirectories(um, unit.Subdirectories, requestedVersion)
	if err != nil {
		return nil, err
	}
	nestedModules, err := getNestedModules(ctx, ds, um, subdirectories)
	if err != nil {
		return nil, err
	}
	readme, err := readmeContent(ctx, unit)
	if err != nil {
		return nil, err
	}
	var (
		docParts           = &dochtml.Parts{}
		docLinks, modLinks []link
		files              []*File
		synopsis           string
		goos, goarch       string
		buildContexts      []internal.BuildContext
	)

	unit.Documentation = cleanDocumentation(unit.Documentation)
	// There should be at most one Documentation.
	var doc *internal.Documentation
	if len(unit.Documentation) > 0 {
		doc = unit.Documentation[0]
	}

	if doc != nil {
		synopsis = doc.Synopsis
		goos = doc.GOOS
		goarch = doc.GOARCH
		buildContexts = unit.BuildContexts
		end := stats.Elapsed(ctx, "DecodePackage")
		docPkg, err := godoc.DecodePackage(doc.Source)
		end()
		if err != nil {
			if errors.Is(err, godoc.ErrInvalidEncodingType) {
				// Instead of returning a 500, return a 404 so the user can
				// reprocess the documentation.
				log.Errorf(ctx, "fetchMainDetails(%q, %q, %q): %v", um.Path, um.ModulePath, um.Version, err)
				return nil, errUnitNotFoundWithoutFetch
			}
			return nil, err
		}

		docParts, err = getHTML(ctx, unit, docPkg, unit.SymbolHistory, bc)
		// If err  is ErrTooLarge, then docBody will have an appropriate message.
		if err != nil && !errors.Is(err, dochtml.ErrTooLarge) {
			return nil, err
		}
		for _, l := range docParts.Links {
			docLinks = append(docLinks, link{Href: l.Href, Body: l.Text})
		}
		end = stats.Elapsed(ctx, "sourceFiles")
		files = sourceFiles(unit, docPkg)
		end()
	}
	// If the unit is not a module, fetch the module readme to extract its
	// links.
	// In the unlikely event that the module is redistributable but the unit is
	// not, we will not show the module links on the unit page.
	if unit.Path != unit.ModulePath && unit.IsRedistributable {
		modReadme, err := ds.GetModuleReadme(ctx, unit.ModulePath, unit.Version)
		if err != nil && !errors.Is(err, derrors.NotFound) {
			return nil, err
		}
		if err == nil {
			rm, err := processReadme(ctx, modReadme, um.SourceInfo)
			if err != nil {
				return nil, err
			}
			modLinks = rm.Links
		}
	}

	versionType, err := version.ParseType(um.Version)
	if err != nil {
		return nil, err
	}
	isTaggedVersion := versionType != version.TypePseudo
	isStableVersion := semver.Major(um.Version) != "v0" && versionType == version.TypeRelease
	pr := message.NewPrinter(middleware.LanguageTag(ctx))
	return &MainDetails{
		ExpandReadme:      expandReadme,
		Directories:       unitDirectories(append(subdirectories, nestedModules...)),
		Licenses:          transformLicenseMetadata(um.Licenses),
		CommitTime:        absoluteTime(um.CommitTime),
		Readme:            readme.HTML,
		ReadmeOutline:     readme.Outline,
		ReadmeLinks:       readme.Links,
		DocLinks:          docLinks,
		ModuleReadmeLinks: modLinks,
		DocOutline:        docParts.Outline,
		DocBody:           docParts.Body,
		DocSynopsis:       synopsis,
		GOOS:              goos,
		GOARCH:            goarch,
		BuildContexts:     buildContexts,
		SourceFiles:       files,
		RepositoryURL:     um.SourceInfo.RepoURL(),
		SourceURL:         um.SourceInfo.DirectoryURL(internal.Suffix(um.Path, um.ModulePath)),
		MobileOutline:     docParts.MobileOutline,
		NumImports:        pr.Sprint(unit.NumImports),
		ImportedByCount:   pr.Sprint(unit.NumImportedBy),
		IsPackage:         unit.IsPackage(),
		ModFileURL:        um.SourceInfo.ModuleURL() + "/go.mod",
		IsTaggedVersion:   isTaggedVersion,
		IsStableVersion:   isStableVersion,
	}, nil
}

func cleanDocumentation(docs []*internal.Documentation) []*internal.Documentation {
	// If there is more than one row but the first is all/all, ignore the others.
	// Should never happen;  temporary fix until the DB is cleaned up.
	if len(docs) > 1 && docs[0].BuildContext() == internal.BuildContextAll {
		return docs[:1]
	}
	// If there is only one Documentation and it is linux/amd64, then
	// make it all/all.
	//
	// This is temporary, until the next reprocessing. It assumes a unit
	// with a single linux/amd64 actually has only one build context,
	// and hasn't been reprocessed to have all/all.
	//
	// The only effect of this is to prevent "GOOS=linux, GOARCH=amd64" from
	// appearing at the bottom of the doc. That is wrong in the (rather
	// unlikely) case that the package truly only has doc for linux/amd64,
	// but the bug is only cosmetic.
	if len(docs) == 1 && docs[0].GOOS == "linux" && docs[0].GOARCH == "amd64" {
		docs[0].GOOS = internal.All
		docs[0].GOARCH = internal.All
	}
	return docs
}

// readmeContent renders the readme to html and collects the headings
// into an outline.
func readmeContent(ctx context.Context, u *internal.Unit) (_ *Readme, err error) {
	defer derrors.Wrap(&err, "readmeContent(%q, %q, %q)", u.Path, u.ModulePath, u.Version)
	defer stats.Elapsed(ctx, "readmeContent")()
	if !u.IsRedistributable {
		return &Readme{}, nil
	}
	return ProcessReadme(ctx, u)
}

const missingDocReplacement = `<p>Documentation is missing.</p>`

func getHTML(ctx context.Context, u *internal.Unit, docPkg *godoc.Package,
	nameToVersion map[string]string, bc internal.BuildContext) (_ *dochtml.Parts, err error) {
	defer derrors.Wrap(&err, "getHTML(%s)", u.Path)

	if len(u.Documentation[0].Source) > 0 {
		return renderDocParts(ctx, u, docPkg, nameToVersion, bc)
	}
	log.Errorf(ctx, "unit %s (%s@%s) missing documentation source", u.Path, u.ModulePath, u.Version)
	return &dochtml.Parts{Body: template.MustParseAndExecuteToHTML(missingDocReplacement)}, nil
}
