// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package android

import (
	"reflect"
	"sync"

	"github.com/google/blueprint"
)

// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
//
// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies.
// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency.
// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts.

type licensesDependencyTag struct {
	blueprint.BaseDependencyTag
}

func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType {
	// Add the supplied module to the sdk as a license module.
	return LicenseModuleSdkMemberType
}

func (l licensesDependencyTag) ExportMember() bool {
	// The license module will only every be referenced from within the sdk. This will ensure that it
	// gets a unique name and so avoid clashing with the original license module.
	return false
}

var (
	licensesTag = licensesDependencyTag{}

	// License modules, i.e. modules depended upon via a licensesTag, must be automatically added to
	// any sdk/module_exports to which their referencing module is a member.
	_ SdkMemberTypeDependencyTag = licensesTag
)

// Describes the property provided by a module to reference applicable licenses.
type applicableLicensesProperty interface {
	// The name of the property. e.g. default_applicable_licenses or licenses
	getName() string
	// The values assigned to the property. (Must reference license modules.)
	getStrings() []string
}

type applicableLicensesPropertyImpl struct {
	name             string
	licensesProperty *[]string
}

func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
	return applicableLicensesPropertyImpl{
		name:             name,
		licensesProperty: licensesProperty,
	}
}

func (p applicableLicensesPropertyImpl) getName() string {
	return p.name
}

func (p applicableLicensesPropertyImpl) getStrings() []string {
	return *p.licensesProperty
}

// Set the primary applicable licenses property for a module.
func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) {
	module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty)
}

// Storage blob for a package's default_applicable_licenses mapped by package directory.
type licensesContainer struct {
	licenses []string
}

func (r licensesContainer) getLicenses() []string {
	return r.licenses
}

var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap")

// The map from package dir name to default applicable licenses as a licensesContainer.
func moduleToPackageDefaultLicensesMap(config Config) *sync.Map {
	return config.Once(packageDefaultLicensesMap, func() interface{} {
		return &sync.Map{}
	}).(*sync.Map)
}

// Registers the function that maps each package to its default_applicable_licenses.
//
// This goes before defaults expansion so the defaults can pick up the package default.
func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
	ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
}

// Registers the function that gathers the license dependencies for each module.
//
// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
	ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
}

// Registers the function that verifies the licenses and license_kinds dependency types for each module.
func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
	ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
}

// Maps each package to its default applicable licenses.
func licensesPackageMapper(ctx BottomUpMutatorContext) {
	p, ok := ctx.Module().(*packageModule)
	if !ok {
		return
	}

	licenses := getLicenses(ctx, p)

	dir := ctx.ModuleDir()
	c := makeLicensesContainer(licenses)
	moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c)
}

// Copies the default_applicable_licenses property values for mapping by package directory.
func makeLicensesContainer(propVals []string) licensesContainer {
	licenses := make([]string, 0, len(propVals))
	licenses = append(licenses, propVals...)

	return licensesContainer{licenses}
}

// Gathers the applicable licenses into dependency references after defaults expansion.
func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
	m, ok := ctx.Module().(Module)
	if !ok {
		return
	}

	if exemptFromRequiredApplicableLicensesProperty(m) {
		return
	}

	licenses := getLicenses(ctx, m)
	ctx.AddVariationDependencies(nil, licensesTag, licenses...)
}

// Verifies the license and license_kind dependencies are each the correct kind of module.
func licensesDependencyChecker(ctx BottomUpMutatorContext) {
	m, ok := ctx.Module().(Module)
	if !ok {
		return
	}

	// license modules have no licenses, but license_kinds must refer to license_kind modules
	if _, ok := m.(*licenseModule); ok {
		for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
			if _, ok := module.(*licenseKindModule); !ok {
				ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
			}
		}
		return
	}

	if exemptFromRequiredApplicableLicensesProperty(m) {
		return
	}

	for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
		if _, ok := module.(*licenseModule); !ok {
			propertyName := "licenses"
			primaryProperty := m.base().primaryLicensesProperty
			if primaryProperty != nil {
				propertyName = primaryProperty.getName()
			}
			ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
		}
	}
}

// Flattens license and license_kind dependencies into calculated properties.
//
// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer
// only to license_kind modules.
func licensesPropertyFlattener(ctx ModuleContext) {
	m, ok := ctx.Module().(Module)
	if !ok {
		return
	}

	if exemptFromRequiredApplicableLicensesProperty(m) {
		return
	}

	var licenses []string
	for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
		if l, ok := module.(*licenseModule); ok {
			licenses = append(licenses, ctx.OtherModuleName(module))
			if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
				m.base().commonProperties.Effective_package_name = l.properties.Package_name
			}
			mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
			mergePathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
			mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
			mergeStringProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
		} else {
			propertyName := "licenses"
			primaryProperty := m.base().primaryLicensesProperty
			if primaryProperty != nil {
				propertyName = primaryProperty.getName()
			}
			ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
		}
	}

	// Make the license information available for other modules.
	licenseInfo := LicenseInfo{
		Licenses: licenses,
	}
	ctx.SetProvider(LicenseInfoProvider, licenseInfo)
}

// Update a property string array with a distinct union of its values and a list of new values.
func mergeStringProps(prop *[]string, values ...string) {
	*prop = append(*prop, values...)
	*prop = SortedUniqueStrings(*prop)
}

// Update a property Path array with a distinct union of its values and a list of new values.
func mergePathProps(prop *Paths, values ...Path) {
	*prop = append(*prop, values...)
	*prop = SortedUniquePaths(*prop)
}

// Get the licenses property falling back to the package default.
func getLicenses(ctx BaseModuleContext, module Module) []string {
	if exemptFromRequiredApplicableLicensesProperty(module) {
		return nil
	}

	primaryProperty := module.base().primaryLicensesProperty
	if primaryProperty == nil {
		if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
			ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module))
		}
		return nil
	}

	licenses := primaryProperty.getStrings()
	if len(licenses) > 0 {
		s := make(map[string]bool)
		for _, l := range licenses {
			if _, ok := s[l]; ok {
				ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName())
			}
			s[l] = true
		}
		return licenses
	}

	dir := ctx.OtherModuleDir(module)

	moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config())
	value, ok := moduleToApplicableLicenses.Load(dir)
	var c licensesContainer
	if ok {
		c = value.(licensesContainer)
	} else {
		c = licensesContainer{}
	}
	return c.getLicenses()
}

// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
	switch reflect.TypeOf(module).String() {
	case "*android.licenseModule": // is a license, doesn't need one
	case "*android.licenseKindModule": // is a license, doesn't need one
	case "*android.NamespaceModule": // just partitions things, doesn't add anything
	case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses
	case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses
	case "*android.soongConfigStringVariableDummyModule": // used for creating aliases
	case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases
	default:
		return false
	}
	return true
}

// LicenseInfo contains information about licenses for a specific module.
type LicenseInfo struct {
	// The list of license modules this depends upon, either explicitly or through default package
	// configuration.
	Licenses []string
}

var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})
