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

import (
	"bytes"
	"context"
	"sort"
	"strconv"

	"github.com/google/safehtml"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/licenses"
)

// License contains information used for a single license section.
type License struct {
	*licenses.License
	Anchor safehtml.Identifier
	Source string
}

// LicensesDetails contains license information for a package or module.
type LicensesDetails struct {
	Licenses []License
}

// LicenseMetadata contains license metadata that is used in the package
// header.
type LicenseMetadata struct {
	Type   string
	Anchor safehtml.Identifier
}

// fetchLicensesDetails fetches license data for the package version specified by
// path and version from the database and returns a LicensesDetails.
func fetchLicensesDetails(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta) (*LicensesDetails, error) {
	u, err := ds.GetUnit(ctx, um, internal.WithLicenses, internal.BuildContext{})
	if err != nil {
		return nil, err
	}
	return &LicensesDetails{Licenses: transformLicenses(um.ModulePath, um.Version, u.LicenseContents)}, nil
}

// transformLicenses transforms licenses.License into a License
// by adding an anchor field.
func transformLicenses(modulePath, requestedVersion string, dbLicenses []*licenses.License) []License {
	licenses := make([]License, len(dbLicenses))
	var filePaths []string
	for _, l := range dbLicenses {
		filePaths = append(filePaths, l.FilePath)
	}
	anchors := licenseAnchors(filePaths)
	for i, l := range dbLicenses {
		l.Contents = bytes.ReplaceAll(l.Contents, []byte("\r"), nil)
		licenses[i] = License{
			Anchor:  anchors[i],
			License: l,
			Source:  fileSource(modulePath, requestedVersion, l.FilePath),
		}
	}
	return licenses
}

// transformLicenseMetadata transforms licenses.Metadata into a LicenseMetadata
// by adding an anchor field.
func transformLicenseMetadata(dbLicenses []*licenses.Metadata) []LicenseMetadata {
	var mds []LicenseMetadata
	var filePaths []string
	for _, l := range dbLicenses {
		filePaths = append(filePaths, l.FilePath)
	}
	anchors := licenseAnchors(filePaths)
	for i, l := range dbLicenses {
		anchor := anchors[i]
		for _, typ := range l.Types {
			mds = append(mds, LicenseMetadata{
				Type:   typ,
				Anchor: anchor,
			})
		}
	}
	return mds
}

// licenseAnchors returns anchors (HTML identifiers) for all the paths, in the
// same order. If the paths are unique, it ensures that the resulting anchors
// are unique. The argument is modified.
func licenseAnchors(paths []string) []safehtml.Identifier {
	// Remember the original index of each path.
	index := map[string]int{}
	for i, p := range paths {
		index[p] = i
	}
	// Pick a canonical order for the paths, so we assign the same anchors
	// the same set of paths regardless of the order they're given to use.
	sort.Strings(paths)
	ids := make([]safehtml.Identifier, len(paths))
	for i, p := range paths {
		ids[index[p]] = safehtml.IdentifierFromConstantPrefix("lic", strconv.Itoa(i))
	}
	return ids
}
