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

func registerBp2buildDepsMutator(ctx RegisterMutatorsContext) {
	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)

	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
}
