// 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"
	"fmt"
	"strings"

	"android/soong/ui/metrics/bp2build_metrics_proto"

	"github.com/google/blueprint"
	"github.com/google/blueprint/bootstrap"
	"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 = "."
)

type MixedBuildEnabledStatus int

const (
	// This module can be mixed_built.
	MixedBuildEnabled = iota

	// There is a technical incompatibility preventing this module from being
	// bazel-analyzed. Note: the module might also be incompatible.
	TechnicalIncompatibility

	// This module cannot be mixed_built due to some incompatibility with it
	// that is not a platform incompatibility. Example: the module-type is not
	// enabled, or is not bp2build-converted.
	ModuleIncompatibility

	// Missing dependencies. We can't query Bazel for modules if it has missing dependencies, there
	// will be failures.
	ModuleMissingDeps
)

// 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"`

	// If non-nil, indicates that the module could not be converted successfully
	// with bp2build. This will describe the reason the module could not be converted.
	UnconvertedReason *UnconvertedReason

	// The Partition this module will be installed on.
	// TODO(b/306200980) Investigate how to handle modules that are installed in multiple
	// partitions.
	Partition string `blueprint:"mutated"`
}

// The reason a module could not be converted to a BUILD target via bp2build.
// This should match bp2build_metrics_proto.UnconvertedReason, but omits private
// proto-related fields that prevent copying this struct.
type UnconvertedReason struct {
	// Should correspond to a valid value in bp2build_metrics_proto.UnconvertedReasonType.
	// A raw int is used here instead, because blueprint logic requires that all transitive
	// fields of module definitions be primitives.
	ReasonType int
	Detail     string
}

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 ShouldConvertWithBazelContext) bool
	shouldConvertWithBp2build(shouldConvertModuleContext, shouldConvertParams) bool

	// ConvertWithBp2build either converts the module to a Bazel build target or
	// declares the module as unconvertible (for logging and metrics).
	// Modules must implement this function to be bp2build convertible. The function
	// must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or
	// its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible.
	ConvertWithBp2build(ctx Bp2buildMutatorContext)

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

// BazelHandcraftedHook is a load hook to possibly register the current module as
// a "handcrafted" Bazel target of a given name. If the current module should be
// registered in this way, the hook function should return the target name. If
// it should not be registered in this way, this function should return the empty string.
type BazelHandcraftedHook func(ctx LoadHookContext) string

// AddBazelHandcraftedHook adds a load hook to (maybe) mark the given module so that
// it is treated by bp2build as if it has a handcrafted Bazel target.
func AddBazelHandcraftedHook(module BazelModule, hook BazelHandcraftedHook) {
	AddLoadHook(module, func(ctx LoadHookContext) {
		var targetName string = hook(ctx)
		if len(targetName) > 0 {
			moduleDir := ctx.ModuleDir()
			if moduleDir == Bp2BuildTopLevel {
				moduleDir = ""
			}
			label := fmt.Sprintf("//%s:%s", moduleDir, targetName)
			module.bazelProps().Bazel_module.Label = &label
		}
	})
}

// 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)
	}
	panic(fmt.Errorf("requested non-existent label for module %s", module.Name()))
}

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 a MixedBuildEnabledStatus regarding whether
// 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) MixedBuildEnabledStatus {
	platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType)
	if platformIncompatible {
		ctx.Config().LogMixedBuild(ctx, false)
		return TechnicalIncompatibility
	}

	if ctx.Config().AllowMissingDependencies() {
		missingDeps := ctx.getMissingDependencies()
		// If there are missing dependencies, querying Bazel will fail. Soong instead fails at execution
		// time, not loading/analysis. disable mixed builds and fall back to Soong to maintain that
		// behavior.
		if len(missingDeps) > 0 {
			ctx.Config().LogMixedBuild(ctx, false)
			return ModuleMissingDeps
		}
	}

	module := ctx.Module()
	apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
	withinApex := !apexInfo.IsForPlatform()
	mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
		module.Enabled() &&
		convertedToBazel(ctx, module) &&
		ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
	ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)

	if mixedBuildEnabled {
		return MixedBuildEnabled
	}
	return ModuleIncompatibility
}

func isGoModule(module blueprint.Module) bool {
	if _, ok := module.(*bootstrap.GoPackage); ok {
		return true
	}
	if _, ok := module.(*bootstrap.GoBinary); ok {
		return true
	}
	return false
}

// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
	// Special-case bootstrap_go_package and bootstrap_go_binary
	// These do not implement Bazelable, but have been converted
	if isGoModule(module) {
		return true
	}
	b, ok := module.(Bazelable)
	if !ok {
		return false
	}

	return b.HasHandcraftedLabel() || b.shouldConvertWithBp2build(ctx, shouldConvertParams{
		module:     module,
		moduleDir:  ctx.OtherModuleDir(module),
		moduleName: ctx.OtherModuleName(module),
		moduleType: ctx.OtherModuleType(module),
	})
}

type ShouldConvertWithBazelContext interface {
	ModuleErrorf(format string, args ...interface{})
	Module() Module
	Config() Config
	ModuleType() string
	ModuleName() string
	ModuleDir() string
}

// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool {
	return b.shouldConvertWithBp2build(ctx, shouldConvertParams{
		module:     ctx.Module(),
		moduleDir:  ctx.ModuleDir(),
		moduleName: ctx.ModuleName(),
		moduleType: ctx.ModuleType(),
	})
}

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 isPlatformIncompatible(osType OsType, arch ArchType) bool {
	return osType == Windows || // Windows toolchains are not currently supported.
		osType == LinuxBionic || // Linux Bionic toolchains are not currently supported.
		osType == LinuxMusl || // Linux musl toolchains are not currently supported (b/259266326).
		arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported.
}

type shouldConvertModuleContext interface {
	ModuleErrorf(format string, args ...interface{})
	Config() Config
}

type shouldConvertParams struct {
	module     blueprint.Module
	moduleType string
	moduleDir  string
	moduleName string
}

func (b *BazelModuleBase) shouldConvertWithBp2build(ctx shouldConvertModuleContext, p shouldConvertParams) bool {
	if !b.bazelProps().Bazel_module.CanConvertToBazel {
		return false
	}

	module := p.module

	propValue := b.bazelProperties.Bazel_module.Bp2build_available
	packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir)

	// 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 := moduleNameWithPossibleOverride(ctx, module, p.moduleName)
	// use "prebuilt_" + original module name as the java_import(_host) module name,
	// to avoid the failure that a normal module and a prebuilt module with
	// the same name are both allowlisted. This cannot be applied to all the *_import
	// module types. For example, android_library_import has to use original module
	// name here otherwise the *-nodeps targets cannot be handled correctly.
	// TODO(b/304385140): remove this special casing
	if p.moduleType == "java_import" || p.moduleType == "java_import_host" {
		moduleName = module.Name()
	}

	allowlist := ctx.Config().Bp2buildPackageConfig

	moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
	moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType]
	allowlistConvert := moduleNameAllowed || moduleTypeAllowed
	if moduleNameAllowed && moduleTypeAllowed {
		ctx.ModuleErrorf("A module %q of type %q cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert", moduleName, p.moduleType)
		return false
	}

	if allowlist.moduleDoNotConvert[moduleName] {
		if moduleNameAllowed {
			ctx.ModuleErrorf("a module %q cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert", moduleName)
		}
		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.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel()
	ctx.BottomUp("bp2build_deps", bp2buildDepsMutator).Parallel()
}

func bp2buildConversionMutator(ctx BottomUpMutatorContext) {
	// If an existing BUILD file in the module directory has a target defined
	// with this same name as this module, assume that this is an existing
	// definition for this target.
	if ctx.Config().HasBazelBuildTargetInSource(ctx.ModuleDir(), ctx.ModuleName()) {
		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, ctx.ModuleName())
		return
	}
	bModule, ok := ctx.Module().(Bazelable)
	if !ok {
		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
		return
	}
	// There may be cases where the target is created by a macro rather than in a BUILD file, those
	// should be captured as well.
	if bModule.HasHandcraftedLabel() {
		// Defer to the BUILD target. Generating an additional target would
		// cause a BUILD file conflict.
		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
		return
	}
	// TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities.
	if !bModule.shouldConvertWithBp2build(ctx, shouldConvertParams{
		module:     ctx.Module(),
		moduleDir:  ctx.ModuleDir(),
		moduleName: ctx.ModuleName(),
		moduleType: ctx.ModuleType(),
	}) {
		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
		return
	}
	if ctx.Module().base().GetUnconvertedReason() != nil {
		return
	}

	bModule.ConvertWithBp2build(ctx)

	installCtx := &baseModuleContextToModuleInstallPathContext{ctx}
	ctx.Module().base().setPartitionForBp2build(modulePartition(installCtx, true))

	if len(ctx.Module().base().Bp2buildTargets()) == 0 && ctx.Module().base().GetUnconvertedReason() == nil {
		panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
	}

	// If an existing BUILD file in the module directory has a target defined
	// with the same name as any target generated by this module, assume that this
	// is an existing definition for this target. (These generated target names
	// may be different than the module name, as checked at the beginning of this function!)
	for _, targetInfo := range ctx.Module().base().Bp2buildTargets() {
		if ctx.Config().HasBazelBuildTargetInSource(targetInfo.TargetPackage(), targetInfo.TargetName()) {
			// Defer to the BUILD target. Generating an additional target would
			// cause a BUILD file conflict.
			ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, targetInfo.TargetName())
			return
		}
	}
}

// TODO: b/285631638 - Add this as a new mutator to the bp2build conversion mutators.
// Currently, this only exists to prepare test coverage for the launch of this feature.
func bp2buildDepsMutator(ctx BottomUpMutatorContext) {
	if ctx.Module().base().GetUnconvertedReason() != nil {
		return
	}

	if len(ctx.Module().GetMissingBp2buildDeps()) > 0 {
		exampleDep := ctx.Module().GetMissingBp2buildDeps()[0]
		ctx.MarkBp2buildUnconvertible(
			bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, exampleDep)
	}

	// Transitively mark modules unconvertible with the following set of conditions.
	ctx.VisitDirectDeps(func(dep Module) {
		if dep.base().GetUnconvertedReason() == nil {
			return
		}

		if dep.base().GetUnconvertedReason().ReasonType ==
			int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE) {
			return
		}

		if ctx.OtherModuleDependencyTag(dep) != Bp2buildDepTag {
			return
		}

		ctx.MarkBp2buildUnconvertible(
			bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, dep.Name())
	})
}

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

func RunsOn(hostSupported bool, deviceSupported bool, unitTest bool) []string {
	var runsOn []string

	if hostSupported && deviceSupported {
		runsOn = []string{"host_without_device", "device"}
	} else if hostSupported {
		if unitTest {
			runsOn = []string{"host_without_device"}
		} else {
			runsOn = []string{"host_with_device"}
		}
	} else if deviceSupported {
		runsOn = []string{"device"}
	}

	return runsOn
}
