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

	"github.com/google/blueprint"
)

// A sortable component is one whose registration order affects the order in which it is executed
// and so affects the behavior of the build system. As a result it is important for the order in
// which they are registered during tests to match the order used at runtime and so the test
// infrastructure will sort them to match.
//
// The sortable components are mutators, singletons and pre-singletons. Module types are not
// sortable because their order of registration does not affect the runtime behavior.
type sortableComponent interface {
	// componentName returns the name of the component.
	//
	// Uniquely identifies the components within the set of components used at runtimr and during
	// tests.
	componentName() string

	// register registers this component in the supplied context.
	register(ctx *Context)
}

type sortableComponents []sortableComponent

// registerAll registers all components in this slice with the supplied context.
func (r sortableComponents) registerAll(ctx *Context) {
	for _, c := range r {
		c.register(ctx)
	}
}

type moduleType struct {
	name    string
	factory ModuleFactory
}

func (t moduleType) register(ctx *Context) {
	ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
}

var moduleTypes []moduleType
var moduleTypesForDocs = map[string]reflect.Value{}

type singleton struct {
	// True if this should be registered as a pre-singleton, false otherwise.
	pre bool

	name    string
	factory SingletonFactory
}

func newSingleton(name string, factory SingletonFactory) singleton {
	return singleton{false, name, factory}
}

func newPreSingleton(name string, factory SingletonFactory) singleton {
	return singleton{true, name, factory}
}

func (s singleton) componentName() string {
	return s.name
}

func (s singleton) register(ctx *Context) {
	adaptor := SingletonFactoryAdaptor(ctx, s.factory)
	if s.pre {
		ctx.RegisterPreSingletonType(s.name, adaptor)
	} else {
		ctx.RegisterSingletonType(s.name, adaptor)
	}
}

var _ sortableComponent = singleton{}

var singletons sortableComponents
var preSingletons sortableComponents

type mutator struct {
	name            string
	bottomUpMutator blueprint.BottomUpMutator
	topDownMutator  blueprint.TopDownMutator
	parallel        bool
}

var _ sortableComponent = &mutator{}

type ModuleFactory func() Module

// ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module
// into a blueprint.Module and a list of property structs
func ModuleFactoryAdaptor(factory ModuleFactory) blueprint.ModuleFactory {
	return func() (blueprint.Module, []interface{}) {
		module := factory()
		return module, module.GetProperties()
	}
}

type SingletonFactory func() Singleton

// SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting
// a Singleton into a blueprint.Singleton
func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory {
	return func() blueprint.Singleton {
		singleton := factory()
		if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
			registerSingletonMakeVarsProvider(ctx.config, makevars)
		}
		return &singletonAdaptor{Singleton: singleton}
	}
}

func RegisterModuleType(name string, factory ModuleFactory) {
	moduleTypes = append(moduleTypes, moduleType{name, factory})
	RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
}

// RegisterModuleTypeForDocs associates a module type name with a reflect.Value of the factory
// function that has documentation for the module type.  It is normally called automatically
// by RegisterModuleType, but can be called manually after RegisterModuleType in order to
// override the factory method used for documentation, for example if the method passed to
// RegisterModuleType was a lambda.
func RegisterModuleTypeForDocs(name string, factory reflect.Value) {
	moduleTypesForDocs[name] = factory
}

func RegisterSingletonType(name string, factory SingletonFactory) {
	singletons = append(singletons, newSingleton(name, factory))
}

func RegisterPreSingletonType(name string, factory SingletonFactory) {
	preSingletons = append(preSingletons, newPreSingleton(name, factory))
}

type Context struct {
	*blueprint.Context
	config Config
}

func NewContext(config Config) *Context {
	ctx := &Context{blueprint.NewContext(), config}
	ctx.SetSrcDir(absSrcDir)
	return ctx
}

// RegisterForBazelConversion registers an alternate shadow pipeline of
// singletons, module types and mutators to register for converting Blueprint
// files to semantically equivalent BUILD files.
func (ctx *Context) RegisterForBazelConversion() {
	for _, t := range moduleTypes {
		t.register(ctx)
	}

	// Required for SingletonModule types, even though we are not using them.
	for _, t := range singletons {
		t.register(ctx)
	}

	RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
}

// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
	preSingletons.registerAll(ctx)

	for _, t := range moduleTypes {
		t.register(ctx)
	}

	mutators := collateGloballyRegisteredMutators()
	mutators.registerAll(ctx)

	singletons := collateGloballyRegisteredSingletons()
	singletons.registerAll(ctx)
}

func collateGloballyRegisteredSingletons() sortableComponents {
	allSingletons := append(sortableComponents(nil), singletons...)
	allSingletons = append(allSingletons,
		singleton{false, "bazeldeps", BazelSingleton},

		// Register phony just before makevars so it can write out its phony rules as Make rules
		singleton{false, "phony", phonySingletonFactory},

		// Register makevars after other singletons so they can export values through makevars
		singleton{false, "makevars", makeVarsSingletonFunc},

		// Register env and ninjadeps last so that they can track all used environment variables and
		// Ninja file dependencies stored in the config.
		singleton{false, "env", EnvSingleton},
		singleton{false, "ninjadeps", ninjaDepsSingletonFactory},
	)

	return allSingletons
}

func ModuleTypeFactories() map[string]ModuleFactory {
	ret := make(map[string]ModuleFactory)
	for _, t := range moduleTypes {
		ret[t.name] = t.factory
	}
	return ret
}

func ModuleTypeFactoriesForDocs() map[string]reflect.Value {
	return moduleTypesForDocs
}

// Interface for registering build components.
//
// Provided to allow registration of build components to be shared between the runtime
// and test environments.
type RegistrationContext interface {
	RegisterModuleType(name string, factory ModuleFactory)
	RegisterSingletonModuleType(name string, factory SingletonModuleFactory)
	RegisterPreSingletonType(name string, factory SingletonFactory)
	RegisterSingletonType(name string, factory SingletonFactory)
	PreArchMutators(f RegisterMutatorFunc)

	// Register pre arch mutators that are hard coded into mutator.go.
	//
	// Only registers mutators for testing, is a noop on the InitRegistrationContext.
	HardCodedPreArchMutators(f RegisterMutatorFunc)

	PreDepsMutators(f RegisterMutatorFunc)
	PostDepsMutators(f RegisterMutatorFunc)
	FinalDepsMutators(f RegisterMutatorFunc)
}

// Used to register build components from an init() method, e.g.
//
// init() {
//   RegisterBuildComponents(android.InitRegistrationContext)
// }
//
// func RegisterBuildComponents(ctx android.RegistrationContext) {
//   ctx.RegisterModuleType(...)
//   ...
// }
//
// Extracting the actual registration into a separate RegisterBuildComponents(ctx) function
// allows it to be used to initialize test context, e.g.
//
//   ctx := android.NewTestContext(config)
//   RegisterBuildComponents(ctx)
var InitRegistrationContext RegistrationContext = &initRegistrationContext{
	moduleTypes:    make(map[string]ModuleFactory),
	singletonTypes: make(map[string]SingletonFactory),
}

// Make sure the TestContext implements RegistrationContext.
var _ RegistrationContext = (*TestContext)(nil)

type initRegistrationContext struct {
	moduleTypes        map[string]ModuleFactory
	singletonTypes     map[string]SingletonFactory
	preSingletonTypes  map[string]SingletonFactory
	moduleTypesForDocs map[string]reflect.Value
}

func (ctx *initRegistrationContext) RegisterModuleType(name string, factory ModuleFactory) {
	if _, present := ctx.moduleTypes[name]; present {
		panic(fmt.Sprintf("module type %q is already registered", name))
	}
	ctx.moduleTypes[name] = factory
	RegisterModuleType(name, factory)
	RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
}

func (ctx *initRegistrationContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
	s, m := SingletonModuleFactoryAdaptor(name, factory)
	ctx.RegisterSingletonType(name, s)
	ctx.RegisterModuleType(name, m)
	// Overwrite moduleTypesForDocs with the original factory instead of the lambda returned by
	// SingletonModuleFactoryAdaptor so that docs can find the module type documentation on the
	// factory method.
	RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
}

func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) {
	if _, present := ctx.singletonTypes[name]; present {
		panic(fmt.Sprintf("singleton type %q is already registered", name))
	}
	ctx.singletonTypes[name] = factory
	RegisterSingletonType(name, factory)
}

func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
	if _, present := ctx.preSingletonTypes[name]; present {
		panic(fmt.Sprintf("pre singleton type %q is already registered", name))
	}
	ctx.preSingletonTypes[name] = factory
	RegisterPreSingletonType(name, factory)
}

func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) {
	PreArchMutators(f)
}

func (ctx *initRegistrationContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
	// Nothing to do as the mutators are hard code in preArch in mutator.go
}

func (ctx *initRegistrationContext) PreDepsMutators(f RegisterMutatorFunc) {
	PreDepsMutators(f)
}

func (ctx *initRegistrationContext) PostDepsMutators(f RegisterMutatorFunc) {
	PostDepsMutators(f)
}

func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) {
	FinalDepsMutators(f)
}
