// 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 {
	IsRedistributable bool
	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.WithMain|internal.WithLicenses, internal.BuildContext{})
	if err != nil {
		return nil, err
	}
	return &LicensesDetails{IsRedistributable: u.IsRedistributable, 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
}
