// 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 (
	"bufio"
	"errors"
	"strings"

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

	"android/soong/android/allowlists"
)

const (
	// A sentinel value to be used as a key in Bp2BuildConfig for modules with
	// no package path. This is also the module dir for top level Android.bp
	// modules.
	Bp2BuildTopLevel = "."
)

// FileGroupAsLibrary describes a filegroup module that is converted to some library
// such as aidl_library or proto_library.
type FileGroupAsLibrary interface {
	ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
	ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool
	GetAidlLibraryLabel(ctx BazelConversionPathContext) string
	GetProtoLibraryLabel(ctx BazelConversionPathContext) string
}

type BazelConversionStatus struct {
	// Information about _all_ bp2build targets generated by this module. Multiple targets are
	// supported as Soong handles some things within a single target that we may choose to split into
	// multiple targets, e.g. renderscript, protos, yacc within a cc module.
	Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`

	// UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
	// Bazel
	UnconvertedDeps []string `blueprint:"mutated"`

	// MissingBp2buildDep stores the module names of direct dependency that were not found
	MissingDeps []string `blueprint:"mutated"`
}

type bazelModuleProperties struct {
	// The label of the Bazel target replacing this Soong module. When run in conversion mode, this
	// will import the handcrafted build target into the autogenerated file. Note: this may result in
	// a conflict due to duplicate targets if bp2build_available is also set.
	Label *string

	// If true, bp2build will generate the converted Bazel target for this module. Note: this may
	// cause a conflict due to the duplicate targets if label is also set.
	//
	// This is a bool pointer to support tristates: true, false, not set.
	//
	// To opt in a module, set bazel_module: { bp2build_available: true }
	// To opt out a module, set bazel_module: { bp2build_available: false }
	// To defer the default setting for the directory, do not set the value.
	Bp2build_available *bool

	// CanConvertToBazel is set via InitBazelModule to indicate that a module type can be converted to
	// Bazel with Bp2build.
	CanConvertToBazel bool `blueprint:"mutated"`
}

// Properties contains common module properties for Bazel migration purposes.
type properties struct {
	// In "Bazel mixed build" mode, this represents the Bazel target replacing
	// this Soong module.
	Bazel_module bazelModuleProperties
}

// namespacedVariableProperties is a map from a string representing a Soong
// config variable namespace, like "android" or "vendor_name" to a slice of
// pointer to a struct containing a single field called Soong_config_variables
// whose value mirrors the structure in the Blueprint file.
type namespacedVariableProperties map[string][]interface{}

// BazelModuleBase contains the property structs with metadata for modules which can be converted to
// Bazel.
type BazelModuleBase struct {
	bazelProperties properties

	// namespacedVariableProperties is used for soong_config_module_type support
	// in bp2build. Soong config modules allow users to set module properties
	// based on custom product variables defined in Android.bp files. These
	// variables are namespaced to prevent clobbering, especially when set from
	// Makefiles.
	namespacedVariableProperties namespacedVariableProperties

	// baseModuleType is set when this module was created from a module type
	// defined by a soong_config_module_type. Every soong_config_module_type
	// "wraps" another module type, e.g. a soong_config_module_type can wrap a
	// cc_defaults to a custom_cc_defaults, or cc_binary to a custom_cc_binary.
	// This baseModuleType is set to the wrapped module type.
	baseModuleType string
}

// Bazelable is specifies the interface for modules that can be converted to Bazel.
type Bazelable interface {
	bazelProps() *properties
	HasHandcraftedLabel() bool
	HandcraftedLabel() string
	GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
	ShouldConvertWithBp2build(ctx BazelConversionContext) bool
	shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool
	ConvertWithBp2build(ctx TopDownMutatorContext)

	// namespacedVariableProps is a map from a soong config variable namespace
	// (e.g. acme, android) to a map of interfaces{}, which are really
	// reflect.Struct pointers, representing the value of the
	// soong_config_variables property of a module. The struct pointer is the
	// one with the single member called Soong_config_variables, which itself is
	// a struct containing fields for each supported feature in that namespace.
	//
	// The reason for using a slice of interface{} is to support defaults
	// propagation of the struct pointers.
	namespacedVariableProps() namespacedVariableProperties
	setNamespacedVariableProps(props namespacedVariableProperties)
	BaseModuleType() string
	SetBaseModuleType(baseModuleType string)
}

// ApiProvider is implemented by modules that contribute to an API surface
type ApiProvider interface {
	ConvertWithApiBp2build(ctx TopDownMutatorContext)
}

// MixedBuildBuildable is an interface that module types should implement in order
// to be "handled by Bazel" in a mixed build.
type MixedBuildBuildable interface {
	// IsMixedBuildSupported returns true if and only if this module should be
	// "handled by Bazel" in a mixed build.
	// This "escape hatch" allows modules with corner-case scenarios to opt out
	// of being built with Bazel.
	IsMixedBuildSupported(ctx BaseModuleContext) bool

	// QueueBazelCall invokes request-queueing functions on the BazelContext
	// so that these requests are handled when Bazel's cquery is invoked.
	QueueBazelCall(ctx BaseModuleContext)

	// ProcessBazelQueryResponse uses Bazel information (obtained from the BazelContext)
	// to set module fields and providers to propagate this module's metadata upstream.
	// This effectively "bridges the gap" between Bazel and Soong in a mixed build.
	// Soong modules depending on this module should be oblivious to the fact that
	// this module was handled by Bazel.
	ProcessBazelQueryResponse(ctx ModuleContext)
}

// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
type BazelModule interface {
	Module
	Bazelable
}

// InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion
// properties.
func InitBazelModule(module BazelModule) {
	module.AddProperties(module.bazelProps())
	module.bazelProps().Bazel_module.CanConvertToBazel = true
}

// bazelProps returns the Bazel properties for the given BazelModuleBase.
func (b *BazelModuleBase) bazelProps() *properties {
	return &b.bazelProperties
}

func (b *BazelModuleBase) namespacedVariableProps() namespacedVariableProperties {
	return b.namespacedVariableProperties
}

func (b *BazelModuleBase) setNamespacedVariableProps(props namespacedVariableProperties) {
	b.namespacedVariableProperties = props
}

func (b *BazelModuleBase) BaseModuleType() string {
	return b.baseModuleType
}

func (b *BazelModuleBase) SetBaseModuleType(baseModuleType string) {
	b.baseModuleType = baseModuleType
}

// HasHandcraftedLabel returns whether this module has a handcrafted Bazel label.
func (b *BazelModuleBase) HasHandcraftedLabel() bool {
	return b.bazelProperties.Bazel_module.Label != nil
}

// HandcraftedLabel returns the handcrafted label for this module, or empty string if there is none
func (b *BazelModuleBase) HandcraftedLabel() string {
	return proptools.String(b.bazelProperties.Bazel_module.Label)
}

// GetBazelLabel returns the Bazel label for the given BazelModuleBase.
func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
	if b.HasHandcraftedLabel() {
		return b.HandcraftedLabel()
	}
	if b.ShouldConvertWithBp2build(ctx) {
		return bp2buildModuleLabel(ctx, module)
	}
	return "" // no label for unconverted module
}

type Bp2BuildConversionAllowlist struct {
	// Configure modules in these directories to enable bp2build_available: true or false by default.
	defaultConfig allowlists.Bp2BuildConfig

	// Keep any existing BUILD files (and do not generate new BUILD files) for these directories
	// in the synthetic Bazel workspace.
	keepExistingBuildFile map[string]bool

	// Per-module allowlist to always opt modules into both bp2build and Bazel Dev Mode mixed
	// builds. These modules are usually in directories with many other modules that are not ready
	// for conversion.
	//
	// A module can either be in this list or its directory allowlisted entirely
	// in bp2buildDefaultConfig, but not both at the same time.
	moduleAlwaysConvert map[string]bool

	// Per-module-type allowlist to always opt modules in to both bp2build and
	// Bazel Dev Mode mixed builds when they have the same type as one listed.
	moduleTypeAlwaysConvert map[string]bool

	// Per-module denylist to always opt modules out of bp2build conversion.
	moduleDoNotConvert map[string]bool
}

// NewBp2BuildAllowlist creates a new, empty Bp2BuildConversionAllowlist
// which can be populated using builder pattern Set* methods
func NewBp2BuildAllowlist() Bp2BuildConversionAllowlist {
	return Bp2BuildConversionAllowlist{
		allowlists.Bp2BuildConfig{},
		map[string]bool{},
		map[string]bool{},
		map[string]bool{},
		map[string]bool{},
	}
}

// SetDefaultConfig copies the entries from defaultConfig into the allowlist
func (a Bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) Bp2BuildConversionAllowlist {
	if a.defaultConfig == nil {
		a.defaultConfig = allowlists.Bp2BuildConfig{}
	}
	for k, v := range defaultConfig {
		a.defaultConfig[k] = v
	}

	return a
}

// SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist
func (a Bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) Bp2BuildConversionAllowlist {
	if a.keepExistingBuildFile == nil {
		a.keepExistingBuildFile = map[string]bool{}
	}
	for k, v := range keepExistingBuildFile {
		a.keepExistingBuildFile[k] = v
	}

	return a
}

// SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist
func (a Bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) Bp2BuildConversionAllowlist {
	if a.moduleAlwaysConvert == nil {
		a.moduleAlwaysConvert = map[string]bool{}
	}
	for _, m := range moduleAlwaysConvert {
		a.moduleAlwaysConvert[m] = true
	}

	return a
}

// SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist
func (a Bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) Bp2BuildConversionAllowlist {
	if a.moduleTypeAlwaysConvert == nil {
		a.moduleTypeAlwaysConvert = map[string]bool{}
	}
	for _, m := range moduleTypeAlwaysConvert {
		a.moduleTypeAlwaysConvert[m] = true
	}

	return a
}

// SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist
func (a Bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) Bp2BuildConversionAllowlist {
	if a.moduleDoNotConvert == nil {
		a.moduleDoNotConvert = map[string]bool{}
	}
	for _, m := range moduleDoNotConvert {
		a.moduleDoNotConvert[m] = true
	}

	return a
}

// ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be
// added to the build symlink forest based on the current global configuration.
func (a Bp2BuildConversionAllowlist) ShouldKeepExistingBuildFileForDir(dir string) bool {
	if _, ok := a.keepExistingBuildFile[dir]; ok {
		// Exact dir match
		return true
	}
	var i int
	// Check if subtree match
	for {
		j := strings.Index(dir[i:], "/")
		if j == -1 {
			return false //default
		}
		prefix := dir[0 : i+j]
		i = i + j + 1 // skip the "/"
		if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive {
			return true
		}
	}
}

var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
var bp2buildAllowlist OncePer

func GetBp2BuildAllowList() Bp2BuildConversionAllowlist {
	return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} {
		return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig).
			SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile).
			SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList).
			SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList).
			SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList)
	}).(Bp2BuildConversionAllowlist)
}

// MixedBuildsEnabled returns true if a module is ready to be replaced by a
// converted or handcrafted Bazel target. As a side effect, calling this
// method will also log whether this module is mixed build enabled for
// metrics reporting.
func MixedBuildsEnabled(ctx BaseModuleContext) bool {
	module := ctx.Module()
	apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
	withinApex := !apexInfo.IsForPlatform()
	mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
		ctx.Os() != Windows && // Windows toolchains are not currently supported.
		module.Enabled() &&
		convertedToBazel(ctx, module) &&
		ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
	ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
	return mixedBuildEnabled
}

// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
	b, ok := module.(Bazelable)
	if !ok {
		return false
	}
	return b.shouldConvertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
}

// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx BazelConversionContext) bool {
	return b.shouldConvertWithBp2build(ctx, ctx.Module())
}

type bazelOtherModuleContext interface {
	ModuleErrorf(format string, args ...interface{})
	Config() Config
	OtherModuleType(m blueprint.Module) string
	OtherModuleName(m blueprint.Module) string
	OtherModuleDir(m blueprint.Module) string
}

func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool {
	if !b.bazelProps().Bazel_module.CanConvertToBazel {
		return false
	}

	// In api_bp2build mode, all soong modules that can provide API contributions should be converted
	// This is irrespective of its presence/absence in bp2build allowlists
	if ctx.Config().BuildMode == ApiBp2build {
		_, providesApis := module.(ApiProvider)
		return providesApis
	}

	propValue := b.bazelProperties.Bazel_module.Bp2build_available
	packagePath := ctx.OtherModuleDir(module)

	// Modules in unit tests which are enabled in the allowlist by type or name
	// trigger this conditional because unit tests run under the "." package path
	isTestModule := packagePath == Bp2BuildTopLevel && proptools.BoolDefault(propValue, false)
	if isTestModule {
		return true
	}

	moduleName := module.Name()
	allowlist := ctx.Config().Bp2buildPackageConfig
	moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
	moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[ctx.OtherModuleType(module)]
	allowlistConvert := moduleNameAllowed || moduleTypeAllowed
	if moduleNameAllowed && moduleTypeAllowed {
		ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert")
		return false
	}

	if allowlist.moduleDoNotConvert[moduleName] {
		if moduleNameAllowed {
			ctx.ModuleErrorf("a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert")
		}
		return false
	}

	// This is a tristate value: true, false, or unset.
	if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
		if moduleNameAllowed {
			ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
				" or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+
				" Module: '%s'", directoryPath, moduleName)
			return false
		}

		// Allow modules to explicitly opt-out.
		return proptools.BoolDefault(propValue, true)
	}

	// Allow modules to explicitly opt-in.
	return proptools.BoolDefault(propValue, allowlistConvert)
}

// bp2buildDefaultTrueRecursively checks that the package contains a prefix from the
// set of package prefixes where all modules must be converted. That is, if the
// package is x/y/z, and the list contains either x, x/y, or x/y/z, this function will
// return true.
//
// However, if the package is x/y, and it matches a Bp2BuildDefaultFalse "x/y" entry
// exactly, this module will return false early.
//
// This function will also return false if the package doesn't match anything in
// the config.
//
// This function will also return the allowlist entry which caused a particular
// package to be enabled. Since packages can be enabled via a recursive declaration,
// the path returned will not always be the same as the one provided.
func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2BuildConfig) (bool, string) {
	// Check if the package path has an exact match in the config.
	if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
		return true, packagePath
	} else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively {
		return false, packagePath
	}

	// If not, check for the config recursively.
	packagePrefix := packagePath

	// e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist.
	for strings.Contains(packagePrefix, "/") {
		dirIndex := strings.LastIndex(packagePrefix, "/")
		packagePrefix = packagePrefix[:dirIndex]
		switch value := config[packagePrefix]; value {
		case allowlists.Bp2BuildDefaultTrueRecursively:
			// package contains this prefix and this prefix should convert all modules
			return true, packagePrefix
		case allowlists.Bp2BuildDefaultFalseRecursively:
			//package contains this prefix and this prefix should NOT convert any modules
			return false, packagePrefix
		}
		// Continue to the next part of the package dir.

	}

	return false, packagePath
}

func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
	ctx.TopDown("bp2build_conversion", convertWithBp2build).Parallel()
}

func convertWithBp2build(ctx TopDownMutatorContext) {
	bModule, ok := ctx.Module().(Bazelable)
	if !ok || !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
		return
	}

	bModule.ConvertWithBp2build(ctx)
}

func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) {
	ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel()
}

// Generate API contribution targets if the Soong module provides APIs
func convertWithApiBp2build(ctx TopDownMutatorContext) {
	if m, ok := ctx.Module().(ApiProvider); ok {
		m.ConvertWithApiBp2build(ctx)
	}
}

// GetMainClassInManifest scans the manifest file specified in filepath and returns
// the value of attribute Main-Class in the manifest file if it exists, or returns error.
// WARNING: this is for bp2build converters of java_* modules only.
func GetMainClassInManifest(c Config, filepath string) (string, error) {
	file, err := c.fs.Open(filepath)
	if err != nil {
		return "", err
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "Main-Class:") {
			return strings.TrimSpace(line[len("Main-Class:"):]), nil
		}
	}

	return "", errors.New("Main-Class is not found.")
}

func AttachValidationActions(ctx ModuleContext, outputFilePath Path, validations Paths) ModuleOutPath {
	validatedOutputFilePath := PathForModuleOut(ctx, "validated", outputFilePath.Base())
	ctx.Build(pctx, BuildParams{
		Rule:        CpNoPreserveSymlink,
		Description: "run validations " + outputFilePath.Base(),
		Output:      validatedOutputFilePath,
		Input:       outputFilePath,
		Validations: validations,
	})
	return validatedOutputFilePath
}
