// Copyright 2021 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 (
	"sort"
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

var (
	_ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")

	licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
		Command:        "${licenseMetadataCmd} -o $out @${out}.rsp",
		CommandDeps:    []string{"${licenseMetadataCmd}"},
		Rspfile:        "${out}.rsp",
		RspfileContent: "${args}",
	}, "args")
)

func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
	base := ctx.Module().base()

	if !base.Enabled(ctx) {
		return
	}

	if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
		return
	}

	var outputFiles Paths
	if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
		outputFiles, _ = outputFileProducer.OutputFiles("")
		outputFiles = PathsIfNonNil(outputFiles...)
	}

	// Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
	// doesn't mark the whole module as a container.
	var installFiles InstallPaths
	if len(base.installFiles) > 0 {
		installFiles = InstallPaths{base.installFiles[len(base.installFiles)-1]}
	}

	isContainer := isContainerFromFileExtensions(installFiles, outputFiles)

	var allDepMetadataFiles Paths
	var allDepMetadataArgs []string
	var allDepOutputFiles Paths
	var allDepMetadataDepSets []*DepSet[Path]

	ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
		dep, _ := bpdep.(Module)
		if dep == nil {
			return
		}
		if !dep.Enabled(ctx) {
			return
		}

		// Defaults add properties and dependencies that get processed on their own.
		if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
			return
		}
		// The required dependencies just say modules A and B should be installed together.
		// It doesn't mean that one is built using the other.
		if ctx.OtherModuleDependencyTag(dep) == RequiredDepTag {
			return
		}

		if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
			allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
			if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
				allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
			}

			depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))

			allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)

			if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
				allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
			} else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
				depOutputFiles = PathsIfNonNil(depOutputFiles...)
				allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
			}
		}
	})

	allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
	sort.Strings(allDepMetadataArgs)
	allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)

	var orderOnlyDeps Paths
	var args []string

	if n := ctx.ModuleName(); n != "" {
		args = append(args,
			"-mn "+proptools.NinjaAndShellEscape(n))
	}

	if t := ctx.ModuleType(); t != "" {
		args = append(args,
			"-mt "+proptools.NinjaAndShellEscape(t))
	}

	args = append(args,
		"-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
		"-mc UNKNOWN")

	if p := base.commonProperties.Effective_package_name; p != nil {
		args = append(args,
			`-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
	}

	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))

	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))

	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))

	if isContainer {
		transitiveDeps := Paths(NewDepSet[Path](TOPOLOGICAL, nil, allDepMetadataDepSets).ToList())
		args = append(args,
			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
		orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
	} else {
		args = append(args,
			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
		orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
	}

	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))

	// Install map
	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))

	// Built files
	if len(outputFiles) > 0 {
		args = append(args,
			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
	}

	// Installed files
	args = append(args,
		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))

	if isContainer {
		args = append(args, "--is_container")
	}

	ctx.Build(pctx, BuildParams{
		Rule:        licenseMetadataRule,
		Output:      licenseMetadataFile,
		OrderOnly:   orderOnlyDeps,
		Description: "license metadata",
		Args: map[string]string{
			"args": strings.Join(args, " "),
		},
	})

	SetProvider(ctx, LicenseMetadataProvider, &LicenseMetadataInfo{
		LicenseMetadataPath:   licenseMetadataFile,
		LicenseMetadataDepSet: NewDepSet(TOPOLOGICAL, Paths{licenseMetadataFile}, allDepMetadataDepSets),
	})
}

func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
	var paths Paths
	if len(installPaths) > 0 {
		paths = installPaths.Paths()
	} else {
		paths = builtPaths
	}

	for _, path := range paths {
		switch path.Ext() {
		case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex", ".capex":
			return true
		}
	}

	return false
}

// LicenseMetadataProvider is used to propagate license metadata paths between modules.
var LicenseMetadataProvider = blueprint.NewProvider[*LicenseMetadataInfo]()

// LicenseMetadataInfo stores the license metadata path for a module.
type LicenseMetadataInfo struct {
	LicenseMetadataPath   Path
	LicenseMetadataDepSet *DepSet[Path]
}

// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
// a string, or an empty string if there are none.
func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
	if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
		annos := annoTag.LicenseAnnotations()
		if len(annos) > 0 {
			annoStrings := make([]string, len(annos))
			for i, s := range annos {
				annoStrings[i] = string(s)
			}
			return ":" + strings.Join(annoStrings, ",")
		}
	}
	return ""
}

// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
// list of license dependency annotations.
type LicenseAnnotationsDependencyTag interface {
	LicenseAnnotations() []LicenseAnnotation
}

// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
// license information.
type LicenseAnnotation string

const (
	// LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
	// of dependency tags when the usage of the dependency is dynamic, for example a shared library
	// linkage for native modules or as a classpath library for java modules.
	//
	// Dependency tags that need to always return LicenseAnnotationSharedDependency
	// can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
	LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"

	// LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
	// dependency tags when the dependency is used as a toolchain.
	//
	// Dependency tags that need to always return LicenseAnnotationToolchain
	// can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
	LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
)

// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
type LicenseAnnotationSharedDependencyTag struct{}

func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
	return []LicenseAnnotation{LicenseAnnotationSharedDependency}
}

// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
// LicenseAnnotations that always returns LicenseAnnotationToolchain.
type LicenseAnnotationToolchainDependencyTag struct{}

func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
	return []LicenseAnnotation{LicenseAnnotationToolchain}
}
