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

	"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.(Module).base().module == nil {
		panic("InitAndroidModule must be called before InitDefaultableModule")
	}
	module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)

	module.AddProperties(module.defaults())

	module.base().customizableProperties = module.GetProperties()
}

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

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

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

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

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

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

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

	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)

	base.module = module
}

var _ Defaults = (*DefaultsModuleBase)(nil)

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

	for _, defaults := range defaultsList {
		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)
	}
}
