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

import (
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/google/blueprint"
)

// BazelTargetModuleProperties contain properties and metadata used for
// Blueprint to BUILD file conversion.
type BazelTargetModuleProperties struct {
	// The Bazel rule class for this target.
	Rule_class string `blueprint:"mutated"`

	// The target label for the bzl file containing the definition of the rule class.
	Bzl_load_location string `blueprint:"mutated"`
}

var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")

// Label is used to represent a Bazel compatible Label. Also stores the original
// bp text to support string replacement.
type Label struct {
	// The string representation of a Bazel target label. This can be a relative
	// or fully qualified label. These labels are used for generating BUILD
	// files with bp2build.
	Label string

	// The original Soong/Blueprint module name that the label was derived from.
	// This is used for replacing references to the original name with the new
	// label, for example in genrule cmds.
	//
	// While there is a reversible 1:1 mapping from the module name to Bazel
	// label with bp2build that could make computing the original module name
	// from the label automatic, it is not the case for handcrafted targets,
	// where modules can have a custom label mapping through the { bazel_module:
	// { label: <label> } } property.
	//
	// With handcrafted labels, those modules don't go through bp2build
	// conversion, but relies on handcrafted targets in the source tree.
	OriginalModuleName string
}

// LabelList is used to represent a list of Bazel labels.
type LabelList struct {
	Includes []Label
	Excludes []Label
}

// MakeLabelList creates a LabelList from a list Label
func MakeLabelList(labels []Label) LabelList {
	return LabelList{
		Includes: labels,
		Excludes: nil,
	}
}

// MakeLabelListFromTargetNames creates a LabelList from unqualified target names
// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets
func MakeLabelListFromTargetNames(targetNames []string) LabelList {
	labels := []Label{}
	for _, name := range targetNames {
		label := Label{Label: ":" + name}
		labels = append(labels, label)
	}
	return MakeLabelList(labels)
}

func (ll *LabelList) Equals(other LabelList) bool {
	if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
		return false
	}
	for i, _ := range ll.Includes {
		if ll.Includes[i] != other.Includes[i] {
			return false
		}
	}
	for i, _ := range ll.Excludes {
		if ll.Excludes[i] != other.Excludes[i] {
			return false
		}
	}
	return true
}

func (ll *LabelList) IsNil() bool {
	return ll.Includes == nil && ll.Excludes == nil
}

func (ll *LabelList) IsEmpty() bool {
	return len(ll.Includes) == 0 && len(ll.Excludes) == 0
}

func (ll *LabelList) deepCopy() LabelList {
	return LabelList{
		Includes: ll.Includes[:],
		Excludes: ll.Excludes[:],
	}
}

// uniqueParentDirectories returns a list of the unique parent directories for
// all files in ll.Includes.
func (ll *LabelList) uniqueParentDirectories() []string {
	dirMap := map[string]bool{}
	for _, label := range ll.Includes {
		dirMap[filepath.Dir(label.Label)] = true
	}
	dirs := []string{}
	for dir := range dirMap {
		dirs = append(dirs, dir)
	}
	return dirs
}

// Add inserts the label Label at the end of the LabelList.Includes.
func (ll *LabelList) Add(label *Label) {
	if label == nil {
		return
	}
	ll.Includes = append(ll.Includes, *label)
}

// AddExclude inserts the label Label at the end of the LabelList.Excludes.
func (ll *LabelList) AddExclude(label *Label) {
	if label == nil {
		return
	}
	ll.Excludes = append(ll.Excludes, *label)
}

// Append appends the fields of other labelList to the corresponding fields of ll.
func (ll *LabelList) Append(other LabelList) {
	if len(ll.Includes) > 0 || len(other.Includes) > 0 {
		ll.Includes = append(ll.Includes, other.Includes...)
	}
	if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
		ll.Excludes = append(other.Excludes, other.Excludes...)
	}
}

// Partition splits a LabelList into two LabelLists depending on the return value
// of the predicate.
// This function preserves the Includes and Excludes, but it does not provide
// that information to the partition function.
func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) {
	predicated := LabelList{}
	unpredicated := LabelList{}
	for _, include := range ll.Includes {
		if predicate(include) {
			predicated.Add(&include)
		} else {
			unpredicated.Add(&include)
		}
	}
	for _, exclude := range ll.Excludes {
		if predicate(exclude) {
			predicated.AddExclude(&exclude)
		} else {
			unpredicated.AddExclude(&exclude)
		}
	}
	return predicated, unpredicated
}

// UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
// the slice in a sorted order.
func UniqueSortedBazelLabels(originalLabels []Label) []Label {
	uniqueLabelsSet := make(map[Label]bool)
	for _, l := range originalLabels {
		uniqueLabelsSet[l] = true
	}
	var uniqueLabels []Label
	for l, _ := range uniqueLabelsSet {
		uniqueLabels = append(uniqueLabels, l)
	}
	sort.SliceStable(uniqueLabels, func(i, j int) bool {
		return uniqueLabels[i].Label < uniqueLabels[j].Label
	})
	return uniqueLabels
}

func FirstUniqueBazelLabels(originalLabels []Label) []Label {
	var labels []Label
	found := make(map[Label]bool, len(originalLabels))
	for _, l := range originalLabels {
		if _, ok := found[l]; ok {
			continue
		}
		labels = append(labels, l)
		found[l] = true
	}
	return labels
}

func FirstUniqueBazelLabelList(originalLabelList LabelList) LabelList {
	var uniqueLabelList LabelList
	uniqueLabelList.Includes = FirstUniqueBazelLabels(originalLabelList.Includes)
	uniqueLabelList.Excludes = FirstUniqueBazelLabels(originalLabelList.Excludes)
	return uniqueLabelList
}

func UniqueSortedBazelLabelList(originalLabelList LabelList) LabelList {
	var uniqueLabelList LabelList
	uniqueLabelList.Includes = UniqueSortedBazelLabels(originalLabelList.Includes)
	uniqueLabelList.Excludes = UniqueSortedBazelLabels(originalLabelList.Excludes)
	return uniqueLabelList
}

// Subtract needle from haystack
func SubtractStrings(haystack []string, needle []string) []string {
	// This is really a set
	needleMap := make(map[string]bool)
	for _, s := range needle {
		needleMap[s] = true
	}

	var strings []string
	for _, s := range haystack {
		if exclude := needleMap[s]; !exclude {
			strings = append(strings, s)
		}
	}

	return strings
}

// Subtract needle from haystack
func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
	// This is really a set
	needleMap := make(map[Label]bool)
	for _, s := range needle {
		needleMap[s] = true
	}

	var labels []Label
	for _, label := range haystack {
		if exclude := needleMap[label]; !exclude {
			labels = append(labels, label)
		}
	}

	return labels
}

// Appends two LabelLists, returning the combined list.
func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
	var result LabelList
	result.Includes = append(a.Includes, b.Includes...)
	result.Excludes = append(a.Excludes, b.Excludes...)
	return result
}

// Subtract needle from haystack
func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
	var result LabelList
	result.Includes = SubtractBazelLabels(haystack.Includes, needle.Includes)
	// NOTE: Excludes are intentionally not subtracted
	result.Excludes = haystack.Excludes
	return result
}

type Attribute interface {
	HasConfigurableValues() bool
}

type labelSelectValues map[string]*Label

type configurableLabels map[ConfigurationAxis]labelSelectValues

func (cl configurableLabels) setValueForAxis(axis ConfigurationAxis, config string, value *Label) {
	if cl[axis] == nil {
		cl[axis] = make(labelSelectValues)
	}
	cl[axis][config] = value
}

// Represents an attribute whose value is a single label
type LabelAttribute struct {
	Value *Label

	ConfigurableValues configurableLabels
}

func (la *LabelAttribute) axisTypes() map[configurationType]bool {
	types := map[configurationType]bool{}
	for k := range la.ConfigurableValues {
		if len(la.ConfigurableValues[k]) > 0 {
			types[k.configurationType] = true
		}
	}
	return types
}

// Collapse reduces the configurable axes of the label attribute to a single axis.
// This is necessary for final writing to bp2build, as a configurable label
// attribute can only be comprised by a single select.
func (la *LabelAttribute) Collapse() error {
	axisTypes := la.axisTypes()
	_, containsOs := axisTypes[os]
	_, containsArch := axisTypes[arch]
	_, containsOsArch := axisTypes[osArch]
	_, containsProductVariables := axisTypes[productVariables]
	if containsProductVariables {
		if containsOs || containsArch || containsOsArch {
			if containsArch {
				allProductVariablesAreArchVariant := true
				for k := range la.ConfigurableValues {
					if k.configurationType == productVariables && k.outerAxisType != arch {
						allProductVariablesAreArchVariant = false
					}
				}
				if !allProductVariablesAreArchVariant {
					return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
				}
			} else {
				return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
			}
		}
	}
	if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
		// If a bool attribute has both os and arch configuration axes, the only
		// way to successfully union their values is to increase the granularity
		// of the configuration criteria to os_arch.
		for osType, supportedArchs := range osToArchMap {
			for _, supportedArch := range supportedArchs {
				osArch := osArchString(osType, supportedArch)
				if archOsVal := la.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
					// Do nothing, as the arch_os is explicitly defined already.
				} else {
					archVal := la.SelectValue(ArchConfigurationAxis, supportedArch)
					osVal := la.SelectValue(OsConfigurationAxis, osType)
					if osVal != nil && archVal != nil {
						// In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
						// runs after os mutator.
						la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
					} else if osVal != nil && archVal == nil {
						la.SetSelectValue(OsArchConfigurationAxis, osArch, *osVal)
					} else if osVal == nil && archVal != nil {
						la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
					}
				}
			}
		}
		// All os_arch values are now set. Clear os and arch axes.
		delete(la.ConfigurableValues, ArchConfigurationAxis)
		delete(la.ConfigurableValues, OsConfigurationAxis)
	}
	return nil
}

// HasConfigurableValues returns whether there are configurable values set for this label.
func (la LabelAttribute) HasConfigurableValues() bool {
	for _, selectValues := range la.ConfigurableValues {
		if len(selectValues) > 0 {
			return true
		}
	}
	return false
}

// SetValue sets the base, non-configured value for the Label
func (la *LabelAttribute) SetValue(value Label) {
	la.SetSelectValue(NoConfigAxis, "", value)
}

// SetSelectValue set a value for a bazel select for the given axis, config and value.
func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string, value Label) {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		la.Value = &value
	case arch, os, osArch, productVariables, osAndInApex:
		if la.ConfigurableValues == nil {
			la.ConfigurableValues = make(configurableLabels)
		}
		la.ConfigurableValues.setValueForAxis(axis, config, &value)
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SelectValue gets a value for a bazel select for the given axis and config.
func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *Label {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		return la.Value
	case arch, os, osArch, productVariables, osAndInApex:
		return la.ConfigurableValues[axis][config]
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis {
	keys := make([]ConfigurationAxis, 0, len(la.ConfigurableValues))
	for k := range la.ConfigurableValues {
		keys = append(keys, k)
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
	return keys
}

// MakeLabelAttribute turns a string into a LabelAttribute
func MakeLabelAttribute(label string) *LabelAttribute {
	return &LabelAttribute{
		Value: &Label{
			Label: label,
		},
	}
}

type configToBools map[string]bool

func (ctb configToBools) setValue(config string, value *bool) {
	if value == nil {
		if _, ok := ctb[config]; ok {
			delete(ctb, config)
		}
		return
	}
	ctb[config] = *value
}

type configurableBools map[ConfigurationAxis]configToBools

func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) {
	if cb[axis] == nil {
		cb[axis] = make(configToBools)
	}
	cb[axis].setValue(config, value)
}

// BoolAttribute represents an attribute whose value is a single bool but may be configurable..
type BoolAttribute struct {
	Value *bool

	ConfigurableValues configurableBools
}

// HasConfigurableValues returns whether there are configurable values for this attribute.
func (ba BoolAttribute) HasConfigurableValues() bool {
	for _, cfgToBools := range ba.ConfigurableValues {
		if len(cfgToBools) > 0 {
			return true
		}
	}
	return false
}

// SetValue sets value for the no config axis
func (ba *BoolAttribute) SetValue(value *bool) {
	ba.SetSelectValue(NoConfigAxis, "", value)
}

// SetSelectValue sets value for the given axis/config.
func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		ba.Value = value
	case arch, os, osArch, productVariables, osAndInApex:
		if ba.ConfigurableValues == nil {
			ba.ConfigurableValues = make(configurableBools)
		}
		ba.ConfigurableValues.setValueForAxis(axis, config, value)
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// ToLabelListAttribute creates and returns a LabelListAttribute from this
// bool attribute, where each bool in this attribute corresponds to a
// label list value in the resultant attribute.
func (ba *BoolAttribute) ToLabelListAttribute(falseVal LabelList, trueVal LabelList) (LabelListAttribute, error) {
	getLabelList := func(boolPtr *bool) LabelList {
		if boolPtr == nil {
			return LabelList{nil, nil}
		} else if *boolPtr {
			return trueVal
		} else {
			return falseVal
		}
	}

	mainVal := getLabelList(ba.Value)
	if !ba.HasConfigurableValues() {
		return MakeLabelListAttribute(mainVal), nil
	}

	result := LabelListAttribute{}
	if err := ba.Collapse(); err != nil {
		return result, err
	}

	for axis, configToBools := range ba.ConfigurableValues {
		if len(configToBools) < 1 {
			continue
		}
		for config, boolPtr := range configToBools {
			val := getLabelList(&boolPtr)
			if !val.Equals(mainVal) {
				result.SetSelectValue(axis, config, val)
			}
		}
		result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
	}

	return result, nil
}

// Collapse reduces the configurable axes of the boolean attribute to a single axis.
// This is necessary for final writing to bp2build, as a configurable boolean
// attribute can only be comprised by a single select.
func (ba *BoolAttribute) Collapse() error {
	axisTypes := ba.axisTypes()
	_, containsOs := axisTypes[os]
	_, containsArch := axisTypes[arch]
	_, containsOsArch := axisTypes[osArch]
	_, containsProductVariables := axisTypes[productVariables]
	if containsProductVariables {
		if containsOs || containsArch || containsOsArch {
			return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
		}
	}
	if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
		// If a bool attribute has both os and arch configuration axes, the only
		// way to successfully union their values is to increase the granularity
		// of the configuration criteria to os_arch.
		for osType, supportedArchs := range osToArchMap {
			for _, supportedArch := range supportedArchs {
				osArch := osArchString(osType, supportedArch)
				if archOsVal := ba.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
					// Do nothing, as the arch_os is explicitly defined already.
				} else {
					archVal := ba.SelectValue(ArchConfigurationAxis, supportedArch)
					osVal := ba.SelectValue(OsConfigurationAxis, osType)
					if osVal != nil && archVal != nil {
						// In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
						// runs after os mutator.
						ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
					} else if osVal != nil && archVal == nil {
						ba.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
					} else if osVal == nil && archVal != nil {
						ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
					}
				}
			}
		}
		// All os_arch values are now set. Clear os and arch axes.
		delete(ba.ConfigurableValues, ArchConfigurationAxis)
		delete(ba.ConfigurableValues, OsConfigurationAxis)
		// Verify post-condition; this should never fail, provided no additional
		// axes are introduced.
		if len(ba.ConfigurableValues) > 1 {
			panic(fmt.Errorf("error in collapsing attribute: %#v", ba))
		}
	}
	return nil
}

func (ba *BoolAttribute) axisTypes() map[configurationType]bool {
	types := map[configurationType]bool{}
	for k := range ba.ConfigurableValues {
		if len(ba.ConfigurableValues[k]) > 0 {
			types[k.configurationType] = true
		}
	}
	return types
}

// SelectValue gets the value for the given axis/config.
func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		return ba.Value
	case arch, os, osArch, productVariables, osAndInApex:
		if v, ok := ba.ConfigurableValues[axis][config]; ok {
			return &v
		} else {
			return nil
		}
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis {
	keys := make([]ConfigurationAxis, 0, len(ba.ConfigurableValues))
	for k := range ba.ConfigurableValues {
		keys = append(keys, k)
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
	return keys
}

// labelListSelectValues supports config-specific label_list typed Bazel attribute values.
type labelListSelectValues map[string]LabelList

func (ll labelListSelectValues) addSelects(label labelSelectValues) {
	for k, v := range label {
		if label == nil {
			continue
		}
		l := ll[k]
		(&l).Add(v)
		ll[k] = l
	}
}

func (ll labelListSelectValues) appendSelects(other labelListSelectValues, forceSpecifyEmptyList bool) {
	for k, v := range other {
		l := ll[k]
		if forceSpecifyEmptyList && l.IsNil() && !v.IsNil() {
			l.Includes = []Label{}
		}
		(&l).Append(v)
		ll[k] = l
	}
}

// HasConfigurableValues returns whether there are configurable values within this set of selects.
func (ll labelListSelectValues) HasConfigurableValues() bool {
	for _, v := range ll {
		if v.Includes != nil {
			return true
		}
	}
	return false
}

// LabelListAttribute is used to represent a list of Bazel labels as an
// attribute.
type LabelListAttribute struct {
	// The non-configured attribute label list Value. Required.
	Value LabelList

	// The configured attribute label list Values. Optional
	// a map of independent configurability axes
	ConfigurableValues configurableLabelLists

	// If true, differentiate between "nil" and "empty" list. nil means that
	// this attribute should not be specified at all, and "empty" means that
	// the attribute should be explicitly specified as an empty list.
	// This mode facilitates use of attribute defaults: an empty list should
	// override the default.
	ForceSpecifyEmptyList bool

	// If true, signal the intent to the code generator to emit all select keys,
	// even if the Includes list for that key is empty. This mode facilitates
	// specific select statements where an empty list for a non-default select
	// key has a meaning.
	EmitEmptyList bool

	// If a property has struct tag "variant_prepend", this value should
	// be set to True, so that when bp2build generates BUILD.bazel, variant
	// properties(select ...) come before general properties.
	Prepend bool
}

type configurableLabelLists map[ConfigurationAxis]labelListSelectValues

func (cll configurableLabelLists) setValueForAxis(axis ConfigurationAxis, config string, list LabelList) {
	if list.IsNil() {
		if _, ok := cll[axis][config]; ok {
			delete(cll[axis], config)
		}
		return
	}
	if cll[axis] == nil {
		cll[axis] = make(labelListSelectValues)
	}

	cll[axis][config] = list
}

func (cll configurableLabelLists) Append(other configurableLabelLists, forceSpecifyEmptyList bool) {
	for axis, otherSelects := range other {
		selects := cll[axis]
		if selects == nil {
			selects = make(labelListSelectValues, len(otherSelects))
		}
		selects.appendSelects(otherSelects, forceSpecifyEmptyList)
		cll[axis] = selects
	}
}

func (lla *LabelListAttribute) Clone() *LabelListAttribute {
	result := &LabelListAttribute{ForceSpecifyEmptyList: lla.ForceSpecifyEmptyList}
	return result.Append(*lla)
}

// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
func MakeLabelListAttribute(value LabelList) LabelListAttribute {
	return LabelListAttribute{
		Value:              value,
		ConfigurableValues: make(configurableLabelLists),
	}
}

// MakeSingleLabelListAttribute initializes a LabelListAttribute as a non-arch specific list with 1 element, the given Label.
func MakeSingleLabelListAttribute(value Label) LabelListAttribute {
	return MakeLabelListAttribute(MakeLabelList([]Label{value}))
}

func (lla *LabelListAttribute) SetValue(list LabelList) {
	lla.SetSelectValue(NoConfigAxis, "", list)
}

// SetSelectValue set a value for a bazel select for the given axis, config and value.
func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list LabelList) {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		lla.Value = list
	case arch, os, osArch, productVariables, osAndInApex, inApex:
		if lla.ConfigurableValues == nil {
			lla.ConfigurableValues = make(configurableLabelLists)
		}
		lla.ConfigurableValues.setValueForAxis(axis, config, list)
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SelectValue gets a value for a bazel select for the given axis and config.
func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string) LabelList {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		return lla.Value
	case arch, os, osArch, productVariables, osAndInApex, inApex:
		return lla.ConfigurableValues[axis][config]
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
func (lla *LabelListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
	keys := make([]ConfigurationAxis, 0, len(lla.ConfigurableValues))
	for k := range lla.ConfigurableValues {
		keys = append(keys, k)
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
	return keys
}

// Append all values, including os and arch specific ones, from another
// LabelListAttribute to this LabelListAttribute. Returns this LabelListAttribute.
func (lla *LabelListAttribute) Append(other LabelListAttribute) *LabelListAttribute {
	forceSpecifyEmptyList := lla.ForceSpecifyEmptyList || other.ForceSpecifyEmptyList
	if forceSpecifyEmptyList && lla.Value.IsNil() && !other.Value.IsNil() {
		lla.Value.Includes = []Label{}
	}
	lla.Value.Append(other.Value)
	if lla.ConfigurableValues == nil {
		lla.ConfigurableValues = make(configurableLabelLists)
	}
	lla.ConfigurableValues.Append(other.ConfigurableValues, forceSpecifyEmptyList)
	return lla
}

// Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's
// LabelList within the LabelListAttribute
func (lla *LabelListAttribute) Add(label *LabelAttribute) {
	if label == nil {
		return
	}

	lla.Value.Add(label.Value)
	if lla.ConfigurableValues == nil && label.ConfigurableValues != nil {
		lla.ConfigurableValues = make(configurableLabelLists)
	}
	for axis, _ := range label.ConfigurableValues {
		if _, exists := lla.ConfigurableValues[axis]; !exists {
			lla.ConfigurableValues[axis] = make(labelListSelectValues)
		}
		lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis])
	}
}

// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
func (lla LabelListAttribute) HasConfigurableValues() bool {
	for _, selectValues := range lla.ConfigurableValues {
		if len(selectValues) > 0 {
			return true
		}
	}
	return false
}

// IsEmpty returns true if the attribute has no values under any configuration.
func (lla LabelListAttribute) IsEmpty() bool {
	if len(lla.Value.Includes) > 0 {
		return false
	}
	for axis, _ := range lla.ConfigurableValues {
		if lla.ConfigurableValues[axis].HasConfigurableValues() {
			return false
		}
	}
	return true
}

// IsNil returns true if the attribute has not been set for any configuration.
func (lla LabelListAttribute) IsNil() bool {
	if lla.Value.Includes != nil {
		return false
	}
	return !lla.HasConfigurableValues()
}

// Exclude for the given axis, config, removes Includes in labelList from Includes and appends them
// to Excludes. This is to special case any excludes that are not specified in a bp file but need to
// be removed, e.g. if they could cause duplicate element failures.
func (lla *LabelListAttribute) Exclude(axis ConfigurationAxis, config string, labelList LabelList) {
	val := lla.SelectValue(axis, config)
	newList := SubtractBazelLabelList(val, labelList)
	newList.Excludes = append(newList.Excludes, labelList.Includes...)
	lla.SetSelectValue(axis, config, newList)
}

// ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
// the base value and included in default values as appropriate.
func (lla *LabelListAttribute) ResolveExcludes() {
	// If there are OsAndInApexAxis, we need to use
	//   * includes from the OS & in APEX Axis for non-Android configs for libraries that need to be
	//     included in non-Android OSes
	//   * excludes from the OS Axis for non-Android configs, to exclude libraries that should _not_
	//     be included in the non-Android OSes
	if _, ok := lla.ConfigurableValues[OsAndInApexAxis]; ok {
		inApexLabels := lla.ConfigurableValues[OsAndInApexAxis][ConditionsDefaultConfigKey]
		for config, labels := range lla.ConfigurableValues[OsConfigurationAxis] {
			// OsAndroid has already handled its excludes.
			// We only need to copy the excludes from other arches, so if there are none, skip it.
			if config == OsAndroid || len(labels.Excludes) == 0 {
				continue
			}
			lla.ConfigurableValues[OsAndInApexAxis][config] = LabelList{
				Includes: inApexLabels.Includes,
				Excludes: labels.Excludes,
			}
		}
	}

	for axis, configToLabels := range lla.ConfigurableValues {
		baseLabels := lla.Value.deepCopy()
		for config, val := range configToLabels {
			// Exclude config-specific excludes from base value
			lla.Value = SubtractBazelLabelList(lla.Value, LabelList{Includes: val.Excludes})

			// add base values to config specific to add labels excluded by others in this axis
			// then remove all config-specific excludes
			allLabels := baseLabels.deepCopy()
			allLabels.Append(val)
			lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: val.Excludes})
		}

		// After going through all configs, delete the duplicates in the config
		// values that are already in the base Value.
		for config, val := range configToLabels {
			lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(val, lla.Value)
		}

		// Now that the Value list is finalized for this axis, compare it with
		// the original list, and union the difference with the default
		// condition for the axis.
		difference := SubtractBazelLabelList(baseLabels, lla.Value)
		existingDefaults := lla.ConfigurableValues[axis][ConditionsDefaultConfigKey]
		existingDefaults.Append(difference)
		lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = FirstUniqueBazelLabelList(existingDefaults)

		// if everything ends up without includes, just delete the axis
		if !lla.ConfigurableValues[axis].HasConfigurableValues() {
			delete(lla.ConfigurableValues, axis)
		}
	}
}

// Partition splits a LabelListAttribute into two LabelListAttributes depending
// on the return value of the predicate.
// This function preserves the Includes and Excludes, but it does not provide
// that information to the partition function.
func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) {
	predicated := LabelListAttribute{}
	unpredicated := LabelListAttribute{}

	valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate)
	predicated.SetValue(valuePartitionTrue)
	unpredicated.SetValue(valuePartitionFalse)

	for axis, selectValueLabelLists := range lla.ConfigurableValues {
		for config, labelList := range selectValueLabelLists {
			configPredicated, configUnpredicated := labelList.Partition(predicate)
			predicated.SetSelectValue(axis, config, configPredicated)
			unpredicated.SetSelectValue(axis, config, configUnpredicated)
		}
	}

	return predicated, unpredicated
}

// OtherModuleContext is a limited context that has methods with information about other modules.
type OtherModuleContext interface {
	ModuleFromName(name string) (blueprint.Module, bool)
	OtherModuleType(m blueprint.Module) string
	OtherModuleName(m blueprint.Module) string
	OtherModuleDir(m blueprint.Module) string
	ModuleErrorf(fmt string, args ...interface{})
}

// LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed)
// label and whether it was changed.
type LabelMapper func(OtherModuleContext, Label) (string, bool)

// LabelPartition contains descriptions of a partition for labels
type LabelPartition struct {
	// Extensions to include in this partition
	Extensions []string
	// LabelMapper is a function that can map a label to a new label, and indicate whether to include
	// the mapped label in the partition
	LabelMapper LabelMapper
	// Whether to store files not included in any other partition in a group of LabelPartitions
	// Only one partition in a group of LabelPartitions can enabled Keep_remainder
	Keep_remainder bool
}

// LabelPartitions is a map of partition name to a LabelPartition describing the elements of the
// partition
type LabelPartitions map[string]LabelPartition

// filter returns a pointer to a label if the label should be included in the partition or nil if
// not.
func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label {
	if lf.LabelMapper != nil {
		if newLabel, changed := lf.LabelMapper(ctx, label); changed {
			return &Label{newLabel, label.OriginalModuleName}
		}
	}
	for _, ext := range lf.Extensions {
		if strings.HasSuffix(label.Label, ext) {
			return &label
		}
	}

	return nil
}

// PartitionToLabelListAttribute is map of partition name to a LabelListAttribute
type PartitionToLabelListAttribute map[string]LabelListAttribute

type partitionToLabelList map[string]*LabelList

func (p partitionToLabelList) appendIncludes(partition string, label Label) {
	if _, ok := p[partition]; !ok {
		p[partition] = &LabelList{}
	}
	p[partition].Includes = append(p[partition].Includes, label)
}

func (p partitionToLabelList) excludes(partition string, excludes []Label) {
	if _, ok := p[partition]; !ok {
		p[partition] = &LabelList{}
	}
	p[partition].Excludes = excludes
}

// PartitionLabelListAttribute partitions a LabelListAttribute into the requested partitions
func PartitionLabelListAttribute(ctx OtherModuleContext, lla *LabelListAttribute, partitions LabelPartitions) PartitionToLabelListAttribute {
	ret := PartitionToLabelListAttribute{}
	var partitionNames []string
	// Stored as a pointer to distinguish nil (no remainder partition) from empty string partition
	var remainderPartition *string
	for p, f := range partitions {
		partitionNames = append(partitionNames, p)
		if f.Keep_remainder {
			if remainderPartition != nil {
				panic("only one partition can store the remainder")
			}
			// If we take the address of p in a loop, we'll end up with the last value of p in
			// remainderPartition, we want the requested partition
			capturePartition := p
			remainderPartition = &capturePartition
		}
	}

	partitionLabelList := func(axis ConfigurationAxis, config string) {
		value := lla.SelectValue(axis, config)
		partitionToLabels := partitionToLabelList{}
		for _, item := range value.Includes {
			wasFiltered := false
			var inPartition *string
			for partition, f := range partitions {
				filtered := f.filter(ctx, item)
				if filtered == nil {
					// did not match this filter, keep looking
					continue
				}
				wasFiltered = true
				partitionToLabels.appendIncludes(partition, *filtered)
				// don't need to check other partitions if this filter used the item,
				// continue checking if mapped to another name
				if *filtered == item {
					if inPartition != nil {
						ctx.ModuleErrorf("%q was found in multiple partitions: %q, %q", item.Label, *inPartition, partition)
					}
					capturePartition := partition
					inPartition = &capturePartition
				}
			}

			// if not specified in a partition, add to remainder partition if one exists
			if !wasFiltered && remainderPartition != nil {
				partitionToLabels.appendIncludes(*remainderPartition, item)
			}
		}

		// ensure empty lists are maintained
		if value.Excludes != nil {
			for _, partition := range partitionNames {
				partitionToLabels.excludes(partition, value.Excludes)
			}
		}

		for partition, list := range partitionToLabels {
			val := ret[partition]
			(&val).SetSelectValue(axis, config, *list)
			ret[partition] = val
		}
	}

	partitionLabelList(NoConfigAxis, "")
	for axis, configToList := range lla.ConfigurableValues {
		for config, _ := range configToList {
			partitionLabelList(axis, config)
		}
	}
	return ret
}

// StringAttribute corresponds to the string Bazel attribute type with
// support for additional metadata, like configurations.
type StringAttribute struct {
	// The base value of the string attribute.
	Value *string

	// The configured attribute label list Values. Optional
	// a map of independent configurability axes
	ConfigurableValues configurableStrings
}

type configurableStrings map[ConfigurationAxis]stringSelectValues

func (cs configurableStrings) setValueForAxis(axis ConfigurationAxis, config string, str *string) {
	if cs[axis] == nil {
		cs[axis] = make(stringSelectValues)
	}
	var v = ""
	if str != nil {
		v = *str
	}
	cs[axis][config] = v
}

type stringSelectValues map[string]string

// HasConfigurableValues returns true if the attribute contains axis-specific string values.
func (sa StringAttribute) HasConfigurableValues() bool {
	for _, selectValues := range sa.ConfigurableValues {
		if len(selectValues) > 0 {
			return true
		}
	}
	return false
}

// SetSelectValue set a value for a bazel select for the given axis, config and value.
func (sa *StringAttribute) SetSelectValue(axis ConfigurationAxis, config string, str *string) {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		sa.Value = str
	case arch, os, osArch, productVariables:
		if sa.ConfigurableValues == nil {
			sa.ConfigurableValues = make(configurableStrings)
		}
		sa.ConfigurableValues.setValueForAxis(axis, config, str)
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SelectValue gets a value for a bazel select for the given axis and config.
func (sa *StringAttribute) SelectValue(axis ConfigurationAxis, config string) *string {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		return sa.Value
	case arch, os, osArch, productVariables:
		if v, ok := sa.ConfigurableValues[axis][config]; ok {
			return &v
		} else {
			return nil
		}
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
func (sa *StringAttribute) SortedConfigurationAxes() []ConfigurationAxis {
	keys := make([]ConfigurationAxis, 0, len(sa.ConfigurableValues))
	for k := range sa.ConfigurableValues {
		keys = append(keys, k)
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
	return keys
}

// Collapse reduces the configurable axes of the string attribute to a single axis.
// This is necessary for final writing to bp2build, as a configurable string
// attribute can only be comprised by a single select.
func (sa *StringAttribute) Collapse() error {
	axisTypes := sa.axisTypes()
	_, containsOs := axisTypes[os]
	_, containsArch := axisTypes[arch]
	_, containsOsArch := axisTypes[osArch]
	_, containsProductVariables := axisTypes[productVariables]
	if containsProductVariables {
		if containsOs || containsArch || containsOsArch {
			return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
		}
	}
	if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
		// If a bool attribute has both os and arch configuration axes, the only
		// way to successfully union their values is to increase the granularity
		// of the configuration criteria to os_arch.
		for osType, supportedArchs := range osToArchMap {
			for _, supportedArch := range supportedArchs {
				osArch := osArchString(osType, supportedArch)
				if archOsVal := sa.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
					// Do nothing, as the arch_os is explicitly defined already.
				} else {
					archVal := sa.SelectValue(ArchConfigurationAxis, supportedArch)
					osVal := sa.SelectValue(OsConfigurationAxis, osType)
					if osVal != nil && archVal != nil {
						// In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
						// runs after os mutator.
						sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
					} else if osVal != nil && archVal == nil {
						sa.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
					} else if osVal == nil && archVal != nil {
						sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
					}
				}
			}
		}
		// All os_arch values are now set. Clear os and arch axes.
		delete(sa.ConfigurableValues, ArchConfigurationAxis)
		delete(sa.ConfigurableValues, OsConfigurationAxis)
		// Verify post-condition; this should never fail, provided no additional
		// axes are introduced.
		if len(sa.ConfigurableValues) > 1 {
			panic(fmt.Errorf("error in collapsing attribute: %#v", sa))
		}
	}
	return nil
}

func (sa *StringAttribute) axisTypes() map[configurationType]bool {
	types := map[configurationType]bool{}
	for k := range sa.ConfigurableValues {
		if strs := sa.ConfigurableValues[k]; len(strs) > 0 {
			types[k.configurationType] = true
		}
	}
	return types
}

// StringListAttribute corresponds to the string_list Bazel attribute type with
// support for additional metadata, like configurations.
type StringListAttribute struct {
	// The base value of the string list attribute.
	Value []string

	// The configured attribute label list Values. Optional
	// a map of independent configurability axes
	ConfigurableValues configurableStringLists

	// If a property has struct tag "variant_prepend", this value should
	// be set to True, so that when bp2build generates BUILD.bazel, variant
	// properties(select ...) come before general properties.
	Prepend bool
}

// IsEmpty returns true if the attribute has no values under any configuration.
func (sla StringListAttribute) IsEmpty() bool {
	return len(sla.Value) == 0 && !sla.HasConfigurableValues()
}

type configurableStringLists map[ConfigurationAxis]stringListSelectValues

func (csl configurableStringLists) Append(other configurableStringLists) {
	for axis, otherSelects := range other {
		selects := csl[axis]
		if selects == nil {
			selects = make(stringListSelectValues, len(otherSelects))
		}
		selects.appendSelects(otherSelects)
		csl[axis] = selects
	}
}

func (csl configurableStringLists) setValueForAxis(axis ConfigurationAxis, config string, list []string) {
	if csl[axis] == nil {
		csl[axis] = make(stringListSelectValues)
	}
	csl[axis][config] = list
}

type stringListSelectValues map[string][]string

func (sl stringListSelectValues) appendSelects(other stringListSelectValues) {
	for k, v := range other {
		sl[k] = append(sl[k], v...)
	}
}

func (sl stringListSelectValues) hasConfigurableValues(other stringListSelectValues) bool {
	for _, val := range sl {
		if len(val) > 0 {
			return true
		}
	}
	return false
}

// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
func MakeStringListAttribute(value []string) StringListAttribute {
	// NOTE: These strings are not necessarily unique or sorted.
	return StringListAttribute{
		Value:              value,
		ConfigurableValues: make(configurableStringLists),
	}
}

// HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
func (sla StringListAttribute) HasConfigurableValues() bool {
	for _, selectValues := range sla.ConfigurableValues {
		if len(selectValues) > 0 {
			return true
		}
	}
	return false
}

// Append appends all values, including os and arch specific ones, from another
// StringListAttribute to this StringListAttribute
func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute {
	sla.Value = append(sla.Value, other.Value...)
	if sla.ConfigurableValues == nil {
		sla.ConfigurableValues = make(configurableStringLists)
	}
	sla.ConfigurableValues.Append(other.ConfigurableValues)
	return sla
}

func (sla *StringListAttribute) Clone() *StringListAttribute {
	result := &StringListAttribute{}
	return result.Append(*sla)
}

// SetSelectValue set a value for a bazel select for the given axis, config and value.
func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list []string) {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		sla.Value = list
	case arch, os, osArch, productVariables, osAndInApex:
		if sla.ConfigurableValues == nil {
			sla.ConfigurableValues = make(configurableStringLists)
		}
		sla.ConfigurableValues.setValueForAxis(axis, config, list)
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SelectValue gets a value for a bazel select for the given axis and config.
func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config string) []string {
	axis.validateConfig(config)
	switch axis.configurationType {
	case noConfig:
		return sla.Value
	case arch, os, osArch, productVariables, osAndInApex:
		return sla.ConfigurableValues[axis][config]
	default:
		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
	}
}

// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
func (sla *StringListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
	keys := make([]ConfigurationAxis, 0, len(sla.ConfigurableValues))
	for k := range sla.ConfigurableValues {
		keys = append(keys, k)
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
	return keys
}

// DeduplicateAxesFromBase ensures no duplication of items between the no-configuration value and
// configuration-specific values. For example, if we would convert this StringListAttribute as:
//
//	["a", "b", "c"] + select({
//	   "//condition:one": ["a", "d"],
//	   "//conditions:default": [],
//	})
//
// after this function, we would convert this StringListAttribute as:
//
//	["a", "b", "c"] + select({
//	   "//condition:one": ["d"],
//	   "//conditions:default": [],
//	})
func (sla *StringListAttribute) DeduplicateAxesFromBase() {
	base := sla.Value
	for axis, configToList := range sla.ConfigurableValues {
		for config, list := range configToList {
			remaining := SubtractStrings(list, base)
			if len(remaining) == 0 {
				delete(sla.ConfigurableValues[axis], config)
			} else {
				sla.ConfigurableValues[axis][config] = remaining
			}
		}
	}
}

// TryVariableSubstitution, replace string substitution formatting within each string in slice with
// Starlark string.format compatible tag for productVariable.
func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
	ret := make([]string, 0, len(slice))
	changesMade := false
	for _, s := range slice {
		newS, changed := TryVariableSubstitution(s, productVariable)
		ret = append(ret, newS)
		changesMade = changesMade || changed
	}
	return ret, changesMade
}

// TryVariableSubstitution, replace string substitution formatting within s with Starlark
// string.format compatible tag for productVariable.
func TryVariableSubstitution(s string, productVariable string) (string, bool) {
	sub := productVariableSubstitutionPattern.ReplaceAllString(s, "$("+productVariable+")")
	return sub, s != sub
}
