// Copyright 2015 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 (
	"reflect"

	"android/soong/ui/metrics/bp2build_metrics_proto"
	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

type defaultsDependencyTag struct {
	blueprint.BaseDependencyTag
}

var DefaultsDepTag defaultsDependencyTag

type defaultsProperties struct {
	Defaults []string
}

type DefaultableModuleBase struct {
	defaultsProperties            defaultsProperties
	defaultableProperties         []interface{}
	defaultableVariableProperties interface{}

	// The optional hook to call after any defaults have been applied.
	hook DefaultableHook
}

func (d *DefaultableModuleBase) defaults() *defaultsProperties {
	return &d.defaultsProperties
}

func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
	d.defaultableProperties = props
	d.defaultableVariableProperties = variableProperties
}

func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) {
	d.hook = hook
}

func (d *DefaultableModuleBase) CallHookIfAvailable(ctx DefaultableHookContext) {
	if d.hook != nil {
		d.hook(ctx)
	}
}

// Interface that must be supported by any module to which defaults can be applied.
type Defaultable interface {
	// Get a pointer to the struct containing the Defaults property.
	defaults() *defaultsProperties

	// Set the property structures into which defaults will be added.
	setProperties(props []interface{}, variableProperties interface{})

	// Apply defaults from the supplied Defaults to the property structures supplied to
	// setProperties(...).
	applyDefaults(TopDownMutatorContext, []Defaults)

	// Set the hook to be called after any defaults have been applied.
	//
	// Should be used in preference to a AddLoadHook when the behavior of the load
	// hook is dependent on properties supplied in the Android.bp file.
	SetDefaultableHook(hook DefaultableHook)

	// Call the hook if specified.
	CallHookIfAvailable(context DefaultableHookContext)
}

type DefaultableModule interface {
	Module
	Defaultable
}

var _ Defaultable = (*DefaultableModuleBase)(nil)

func InitDefaultableModule(module DefaultableModule) {
	if module.base().module == nil {
		panic("InitAndroidModule must be called before InitDefaultableModule")
	}

	module.setProperties(module.GetProperties(), module.base().variableProperties)

	module.AddProperties(module.defaults())
}

// A restricted subset of context methods, similar to LoadHookContext.
type DefaultableHookContext interface {
	EarlyModuleContext

	CreateModule(ModuleFactory, ...interface{}) Module
	AddMissingDependencies(missingDeps []string)
}

type DefaultableHook func(ctx DefaultableHookContext)

// The Defaults_visibility property.
type DefaultsVisibilityProperties struct {

	// Controls the visibility of the defaults module itself.
	Defaults_visibility []string
}

type DefaultsModuleBase struct {
	DefaultableModuleBase

	// Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
	// target. This is primarily useful for modules that were architecture specific and instead are
	// handled in Bazel as a select().
	BazelModuleBase
}

// The common pattern for defaults modules is to register separate instances of
// the xxxProperties structs in the AddProperties calls, rather than reusing the
// ones inherited from Module.
//
// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
// contain the values that have been set for the defaults module. Rather, to
// retrieve the values it is necessary to iterate over properties(). E.g. to get
// the commonProperties instance that have the real values:
//
//	d := myModule.(Defaults)
//	for _, props := range d.properties() {
//	  if cp, ok := props.(*commonProperties); ok {
//	    ... access property values in cp ...
//	  }
//	}
//
// The rationale is that the properties on a defaults module apply to the
// defaultable modules using it, not to the defaults module itself. E.g. setting
// the "enabled" property false makes inheriting modules disabled by default,
// rather than disabling the defaults module itself.
type Defaults interface {
	Defaultable

	// Although this function is unused it is actually needed to ensure that only modules that embed
	// DefaultsModuleBase will type-assert to the Defaults interface.
	isDefaults() bool

	// Get the structures containing the properties for which defaults can be provided.
	properties() []interface{}

	productVariableProperties() interface{}
}

func (d *DefaultsModuleBase) isDefaults() bool {
	return true
}

type DefaultsModule interface {
	Module
	Defaults
	Bazelable
}

func (d *DefaultsModuleBase) properties() []interface{} {
	return d.defaultableProperties
}

func (d *DefaultsModuleBase) productVariableProperties() interface{} {
	return d.defaultableVariableProperties
}

func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {}

// ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
// *NOT* converted with bp2build
func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
	// Defaults types are never convertible.
	ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
}

func InitDefaultsModule(module DefaultsModule) {
	commonProperties := &commonProperties{}

	module.AddProperties(
		&hostAndDeviceProperties{},
		commonProperties,
		&ApexProperties{},
		&distProperties{})

	// Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
	InitBazelModule(module)
	initAndroidModuleBase(module)
	initProductVariableModule(module)
	initArchModule(module)
	InitDefaultableModule(module)

	// Add properties that will not have defaults applied to them.
	base := module.base()
	defaultsVisibility := &DefaultsVisibilityProperties{}
	module.AddProperties(&base.nameProperties, defaultsVisibility)

	// Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
	// Instead it is stored in a separate instance of commonProperties created above so clear the
	// existing list of properties.
	clearVisibilityProperties(module)

	// The defaults_visibility property controls the visibility of a defaults module so it must be
	// set as the primary property, which also adds it to the list.
	setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)

	// The visibility property needs to be checked (but not parsed) by the visibility module during
	// its checking phase and parsing phase so add it to the list as a normal property.
	AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)

	// The applicable licenses property for defaults is 'licenses'.
	setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
}

var _ Defaults = (*DefaultsModuleBase)(nil)

// applyNamespacedVariableDefaults only runs in bp2build mode for
// defaultable/defaults modules. Its purpose is to merge namespaced product
// variable props from defaults deps, even if those defaults are custom module
// types created from soong_config_module_type, e.g. one that's wrapping a
// cc_defaults or java_defaults.
func applyNamespacedVariableDefaults(defaultDep Defaults, ctx TopDownMutatorContext) {
	var dep, b Bazelable

	dep, ok := defaultDep.(Bazelable)
	if !ok {
		if depMod, ok := defaultDep.(Module); ok {
			// Track that this dependency hasn't been converted to bp2build yet.
			ctx.AddUnconvertedBp2buildDep(depMod.Name())
			return
		} else {
			panic("Expected default dep to be a Module.")
		}
	}

	b, ok = ctx.Module().(Bazelable)
	if !ok {
		return
	}

	// namespacedVariableProps is a map from namespaces (e.g. acme, android,
	// vendor_foo) to a slice of soong_config_variable struct pointers,
	// containing properties for that particular module.
	src := dep.namespacedVariableProps()
	dst := b.namespacedVariableProps()
	if dst == nil {
		dst = make(namespacedVariableProperties)
	}

	// Propagate all soong_config_variable structs from the dep. We'll merge the
	// actual property values later in variable.go.
	for namespace := range src {
		if dst[namespace] == nil {
			dst[namespace] = []interface{}{}
		}
		for _, i := range src[namespace] {
			dst[namespace] = append(dst[namespace], i)
		}
	}

	b.setNamespacedVariableProps(dst)
}

func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
	defaultsList []Defaults) {

	for _, defaults := range defaultsList {
		if ctx.Config().BuildMode == Bp2build {
			applyNamespacedVariableDefaults(defaults, ctx)
		}
		for _, prop := range defaultable.defaultableProperties {
			if prop == defaultable.defaultableVariableProperties {
				defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
			} else {
				defaultable.applyDefaultProperties(ctx, defaults, prop)
			}
		}
	}
}

// Product variable properties need special handling, the type of the filtered product variable
// property struct may not be identical between the defaults module and the defaultable module.
// Use PrependMatchingProperties to apply whichever properties match.
func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
	defaults Defaults, defaultableProp interface{}) {
	if defaultableProp == nil {
		return
	}

	defaultsProp := defaults.productVariableProperties()
	if defaultsProp == nil {
		return
	}

	dst := []interface{}{
		defaultableProp,
		// Put an empty copy of the src properties into dst so that properties in src that are not in dst
		// don't cause a "failed to find property to extend" error.
		proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
	}

	err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
	if err != nil {
		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
		} else {
			panic(err)
		}
	}
}

func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
	defaults Defaults, defaultableProp interface{}) {

	for _, def := range defaults.properties() {
		if proptools.TypeEqual(defaultableProp, def) {
			err := proptools.PrependProperties(defaultableProp, def, nil)
			if err != nil {
				if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
					ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
				} else {
					panic(err)
				}
			}
		}
	}
}

func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
	ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
	ctx.TopDown("defaults", defaultsMutator).Parallel()
}

func defaultsDepsMutator(ctx BottomUpMutatorContext) {
	if defaultable, ok := ctx.Module().(Defaultable); ok {
		ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
	}
}

func defaultsMutator(ctx TopDownMutatorContext) {
	if defaultable, ok := ctx.Module().(Defaultable); ok {
		if len(defaultable.defaults().Defaults) > 0 {
			var defaultsList []Defaults
			seen := make(map[Defaults]bool)

			ctx.WalkDeps(func(module, parent Module) bool {
				if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
					if defaults, ok := module.(Defaults); ok {
						if !seen[defaults] {
							seen[defaults] = true
							defaultsList = append(defaultsList, defaults)
							return len(defaults.defaults().Defaults) > 0
						}
					} else {
						ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
							ctx.OtherModuleName(module))
					}
				}
				return false
			})
			defaultable.applyDefaults(ctx, defaultsList)
		}

		defaultable.CallHookIfAvailable(ctx)
	}
}
