// 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 sample provides functionality for generating sample values of
// the types contained in the internal package.
package sample

import (
	"fmt"
	"math"
	"net/http"
	"path"
	"strings"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"
	"github.com/google/licensecheck"
	oldlicensecheck "github.com/google/licensecheck/old"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/licenses"
	"golang.org/x/pkgsite/internal/source"
	"golang.org/x/pkgsite/internal/stdlib"
)

//go:generate go run gen_documentation.go

// These sample values can be used to construct test cases.
var (
	ModulePath      = "github.com/valid/module_name"
	RepositoryURL   = "https://github.com/valid/module_name"
	VersionString   = "v1.0.0"
	CommitTime      = NowTruncated()
	LicenseType     = "MIT"
	LicenseFilePath = "LICENSE"
	LicenseMetadata = []*licenses.Metadata{
		{
			Types:    []string{LicenseType},
			FilePath: LicenseFilePath,
			OldCoverage: oldlicensecheck.Coverage{
				Percent: 100,
				Match:   []oldlicensecheck.Match{{Name: LicenseType, Type: oldlicensecheck.MIT, Percent: 100}},
			},
		},
	}
	Licenses = []*licenses.License{
		{Metadata: LicenseMetadata[0], Contents: []byte(`Lorem Ipsum`)},
	}
	NonRedistributableLicense = &licenses.License{
		Metadata: &licenses.Metadata{
			FilePath: "NONREDIST_LICENSE",
			Types:    []string{"UNKNOWN"},
		},
		Contents: []byte(`unknown`),
	}
	PackageName    = "foo"
	Suffix         = "foo"
	PackagePath    = path.Join(ModulePath, Suffix)
	V1Path         = PackagePath
	Imports        = []string{"path/to/bar", "fmt"}
	Synopsis       = "This is a package synopsis"
	ReadmeFilePath = "README.md"
	ReadmeContents = "readme"
	GOOS           = "linux"
	GOARCH         = "amd64"
)

// LicenseCmpOpts are options to use when comparing licenses with the cmp package.
var LicenseCmpOpts = []cmp.Option{
	cmp.Comparer(coveragePercentEqual),
	cmpopts.IgnoreFields(licensecheck.Match{}, "Start", "End"),
}

// coveragePercentEqual considers two floats the same if they are within 4
// percentage points, and both are on the same side of 90% (our threshold).
func coveragePercentEqual(a, b float64) bool {
	if (a >= 90) != (b >= 90) {
		return false
	}
	return math.Abs(a-b) <= 4
}

// NowTruncated returns time.Now() truncated to Microsecond precision.
//
// This makes it easier to work with timestamps in PostgreSQL, which have
// Microsecond precision:
//   https://www.postgresql.org/docs/9.1/datatype-datetime.html
func NowTruncated() time.Time {
	return time.Now().In(time.UTC).Truncate(time.Microsecond)
}

func DefaultModule() *internal.Module {
	fp := constructFullPath(ModulePath, Suffix)
	return AddPackage(Module(ModulePath, VersionString), UnitForPackage(fp, ModulePath, VersionString, path.Base(fp), true))
}

// Module creates a Module with the given path and version.
// The list of suffixes is used to create Units within the module.
func Module(modulePath, version string, suffixes ...string) *internal.Module {
	mi := ModuleInfo(modulePath, version)
	m := &internal.Module{
		ModuleInfo: *mi,
		Licenses:   Licenses,
	}
	m.Units = []*internal.Unit{UnitForModuleRoot(mi)}
	for _, s := range suffixes {
		fp := constructFullPath(modulePath, s)
		lp := UnitForPackage(fp, modulePath, VersionString, path.Base(fp), m.IsRedistributable)
		if s != "" {
			AddPackage(m, lp)
		} else {
			u := UnitForPackage(lp.Path, modulePath, version, lp.Name, lp.IsRedistributable)
			m.Units[0].Documentation = u.Documentation
			m.Units[0].Name = u.Name
		}
	}
	return m
}

func UnitForModuleRoot(m *internal.ModuleInfo) *internal.Unit {
	u := &internal.Unit{
		UnitMeta:        *UnitMeta(m.ModulePath, m.ModulePath, m.Version, "", m.IsRedistributable),
		LicenseContents: Licenses,
	}
	u.Readme = &internal.Readme{
		Filepath: ReadmeFilePath,
		Contents: ReadmeContents,
	}
	return u
}

// UnitForPackage constructs a unit with the given module path and suffix.
//
// If modulePath is the standard library, the package path is the
// suffix, which must not be empty. Otherwise, the package path
// is the concatenation of modulePath and suffix.
//
// The package name is last component of the package path.
func UnitForPackage(path, modulePath, version, name string, isRedistributable bool) *internal.Unit {
	return &internal.Unit{
		UnitMeta: *UnitMeta(path, modulePath, version, name, isRedistributable),
		Documentation: []*internal.Documentation{{
			Synopsis: Synopsis,
			Source:   DocumentationSource,
			GOOS:     GOOS,
			GOARCH:   GOARCH,
		}},
		LicenseContents: Licenses,
		Imports:         Imports,
		NumImports:      len(Imports),
	}
}

func AddPackage(m *internal.Module, pkg *internal.Unit) *internal.Module {
	if m.ModulePath != stdlib.ModulePath && !strings.HasPrefix(pkg.Path, m.ModulePath) {
		panic(fmt.Sprintf("package path %q not a prefix of module path %q",
			pkg.Path, m.ModulePath))
	}
	AddUnit(m, UnitForPackage(pkg.Path, m.ModulePath, m.Version, pkg.Name, pkg.IsRedistributable))
	minLen := len(m.ModulePath)
	if m.ModulePath == stdlib.ModulePath {
		minLen = 1
	}
	for pth := pkg.Path; len(pth) > minLen; pth = path.Dir(pth) {
		found := false
		for _, u := range m.Units {
			if u.Path == pth {
				found = true
				break
			}
		}
		if !found {
			AddUnit(m, UnitEmpty(pth, m.ModulePath, m.Version))
		}
	}
	return m
}

func PackageMeta(fullPath string) *internal.PackageMeta {
	return &internal.PackageMeta{
		Path:              fullPath,
		IsRedistributable: true,
		Name:              path.Base(fullPath),
		Synopsis:          Synopsis,
		Licenses:          LicenseMetadata,
	}
}

func ModuleInfo(modulePath, versionString string) *internal.ModuleInfo {
	return &internal.ModuleInfo{
		ModulePath: modulePath,
		Version:    versionString,
		CommitTime: CommitTime,
		// Assume the module path is a GitHub-like repo name.
		SourceInfo:        source.NewGitHubInfo("https://"+modulePath, "", versionString),
		IsRedistributable: true,
		HasGoMod:          true,
	}
}

func DefaultVersionMap() *internal.VersionMap {
	return &internal.VersionMap{
		ModulePath:       ModulePath,
		RequestedVersion: VersionString,
		ResolvedVersion:  VersionString,
		Status:           http.StatusOK,
		GoModPath:        "",
		Error:            "",
	}
}

func AddUnit(m *internal.Module, u *internal.Unit) {
	for _, e := range m.Units {
		if e.Path == u.Path {
			panic(fmt.Sprintf("module already has path %q", e.Path))
		}
	}
	m.Units = append(m.Units, u)
}

func AddLicense(m *internal.Module, lic *licenses.License) {
	m.Licenses = append(m.Licenses, lic)
	dir := path.Dir(lic.FilePath)
	if dir == "." {
		dir = ""
	}
	for _, u := range m.Units {
		if strings.TrimPrefix(u.Path, m.ModulePath+"/") == dir {
			u.Licenses = append(u.Licenses, lic.Metadata)
		}
	}
}

func UnitEmpty(path, modulePath, version string) *internal.Unit {
	return &internal.Unit{
		UnitMeta: *UnitMeta(path, modulePath, version, "", true),
	}
}

func UnitMeta(path, modulePath, version, name string, isRedistributable bool) *internal.UnitMeta {
	return &internal.UnitMeta{
		ModulePath:        modulePath,
		Version:           version,
		Path:              path,
		Name:              name,
		CommitTime:        NowTruncated(),
		IsRedistributable: isRedistributable,
		Licenses:          LicenseMetadata,
		SourceInfo:        source.NewGitHubInfo("https://"+modulePath, "", version),
	}
}

func constructFullPath(modulePath, suffix string) string {
	if modulePath != stdlib.ModulePath {
		return path.Join(modulePath, suffix)
	}
	return suffix
}
