// Copyright 2014 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 blueprint

import (
	"fmt"

	"github.com/google/blueprint/pathtools"
)

type Singleton interface {
	GenerateBuildActions(SingletonContext)
}

type SingletonContext interface {
	// Config returns the config object that was passed to Context.PrepareBuildActions.
	Config() interface{}

	// Name returns the name of the current singleton passed to Context.RegisterSingletonType
	Name() string

	// ModuleName returns the name of the given Module.  See BaseModuleContext.ModuleName for more information.
	ModuleName(module Module) string

	// ModuleDir returns the directory of the given Module.  See BaseModuleContext.ModuleDir for more information.
	ModuleDir(module Module) string

	// ModuleSubDir returns the unique subdirectory name of the given Module.  See ModuleContext.ModuleSubDir for
	// more information.
	ModuleSubDir(module Module) string

	// ModuleType returns the type of the given Module.  See BaseModuleContext.ModuleType for more information.
	ModuleType(module Module) string

	// BlueprintFile returns the path of the Blueprint file that defined the given module.
	BlueprintFile(module Module) string

	// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
	// provider was not set it returns the zero value of the type of the provider, which means the
	// return value can always be type-asserted to the type of the provider.  The return value should
	// always be considered read-only.  It panics if called before the appropriate mutator or
	// GenerateBuildActions pass for the provider on the module.
	ModuleProvider(module Module, provider AnyProviderKey) (any, bool)

	// ModuleErrorf reports an error at the line number of the module type in the module definition.
	ModuleErrorf(module Module, format string, args ...interface{})

	// Errorf reports an error at the specified position of the module definition file.
	Errorf(format string, args ...interface{})

	// OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
	OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})

	// Failed returns true if any errors have been reported.  In most cases the singleton can continue with generating
	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
	// has prevented the singleton from creating necessary data it can return early when Failed returns true.
	Failed() bool

	// Variable creates a new ninja variable scoped to the singleton.  It can be referenced by calls to Rule and Build
	// in the same singleton.
	Variable(pctx PackageContext, name, value string)

	// Rule creates a new ninja rule scoped to the singleton.  It can be referenced by calls to Build in the same
	// singleton.
	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule

	// Build creates a new ninja build statement.
	Build(pctx PackageContext, params BuildParams)

	// RequireNinjaVersion sets the generated ninja manifest to require at least the specified version of ninja.
	RequireNinjaVersion(major, minor, micro int)

	// SetOutDir sets the value of the top-level "builddir" Ninja variable
	// that controls where Ninja stores its build log files.  This value can be
	// set at most one time for a single build, later calls are ignored.
	SetOutDir(pctx PackageContext, value string)

	// AddSubninja adds a ninja file to include with subninja. This should likely
	// only ever be used inside bootstrap to handle glob rules.
	AddSubninja(file string)

	// Eval takes a string with embedded ninja variables, and returns a string
	// with all of the variables recursively expanded. Any variables references
	// are expanded in the scope of the PackageContext.
	Eval(pctx PackageContext, ninjaStr string) (string, error)

	// VisitAllModules calls visit for each defined variant of each module in an unspecified order.
	VisitAllModules(visit func(Module))

	// VisitAllModuleProxies calls visit for each defined variant of each module in an unspecified order.
	VisitAllModuleProxies(visit func(proxy ModuleProxy))

	// VisitAllModules calls pred for each defined variant of each module in an unspecified order, and if pred returns
	// true calls visit.
	VisitAllModulesIf(pred func(Module) bool, visit func(Module))

	// VisitDirectDeps calls visit for each direct dependency of the Module.  If there are
	// multiple direct dependencies on the same module visit will be called multiple times on
	// that module and OtherModuleDependencyTag will return a different tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit
	// function, it may be invalidated by future mutators.
	VisitDirectDeps(module Module, visit func(Module))

	// VisitDirectDepsIf calls pred for each direct dependency of the Module, and if pred
	// returns true calls visit.  If there are multiple direct dependencies on the same module
	// pred and visit will be called multiple times on that module and OtherModuleDependencyTag
	// will return a different tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit
	// function, it may be invalidated by future mutators.
	VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))

	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
	// order. visit will only be called once for any given module, even if there are multiple paths through the
	// dependency tree to the module or multiple direct dependencies with different tags.
	VisitDepsDepthFirst(module Module, visit func(Module))

	// VisitDepsDepthFirst calls pred for each transitive dependency, and if pred returns true calls visit, traversing
	// the dependency tree in depth first order.  visit will only be called once for any given module, even if there are
	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
		visit func(Module))

	// VisitAllModuleVariants calls visit for each variant of the given module.
	VisitAllModuleVariants(module Module, visit func(Module))

	// VisitAllModuleVariantProxies calls visit for each variant of the given module.
	VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))

	// PrimaryModule returns the first variant of the given module.  This can be used to perform
	//	// singleton actions that are only done once for all variants of a module.
	PrimaryModule(module Module) Module

	// IsFinalModule returns if the given module is the last variant. This can be used to perform
	// singleton actions that are only done once for all variants of a module.
	IsFinalModule(module Module) bool

	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
	// primary builder will be rerun whenever the specified files are modified.
	AddNinjaFileDeps(deps ...string)

	// GlobWithDeps returns a list of files and directories that match the
	// specified pattern but do not match any of the patterns in excludes.
	// Any directories will have a '/' suffix. It also adds efficient
	// dependencies to rerun the primary builder whenever a file matching
	// the pattern as added or removed, without rerunning if a file that
	// does not match the pattern is added to a searched directory.
	GlobWithDeps(pattern string, excludes []string) ([]string, error)

	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
	// the singleton to be used in build system tests that run against a mock filesystem.
	Fs() pathtools.FileSystem

	// ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer`.
	// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
	ModuleVariantsFromName(referer Module, name string) []Module

	// HasMutatorFinished returns true if the given mutator has finished running.
	// It will panic if given an invalid mutator name.
	HasMutatorFinished(mutatorName string) bool
}

var _ SingletonContext = (*singletonContext)(nil)

type singletonContext struct {
	name    string
	context *Context
	config  interface{}
	scope   *localScope
	globals *liveTracker

	ninjaFileDeps []string
	errs          []error

	actionDefs localBuildActions
}

func (s *singletonContext) Config() interface{} {
	return s.config
}

func (s *singletonContext) Name() string {
	return s.name
}

func (s *singletonContext) ModuleName(logicModule Module) string {
	return s.context.ModuleName(logicModule)
}

func (s *singletonContext) ModuleDir(logicModule Module) string {
	return s.context.ModuleDir(logicModule)
}

func (s *singletonContext) ModuleSubDir(logicModule Module) string {
	return s.context.ModuleSubDir(logicModule)
}

func (s *singletonContext) ModuleType(logicModule Module) string {
	return s.context.ModuleType(logicModule)
}

func (s *singletonContext) ModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) {
	return s.context.ModuleProvider(getWrappedModule(logicModule), provider)
}

func (s *singletonContext) BlueprintFile(logicModule Module) string {
	return s.context.BlueprintFile(logicModule)
}

func (s *singletonContext) error(err error) {
	if err != nil {
		s.errs = append(s.errs, err)
	}
}

func (s *singletonContext) ModuleErrorf(logicModule Module, format string,
	args ...interface{}) {

	s.error(s.context.ModuleErrorf(logicModule, format, args...))
}

func (s *singletonContext) Errorf(format string, args ...interface{}) {
	// TODO: Make this not result in the error being printed as "internal error"
	s.error(fmt.Errorf(format, args...))
}

func (s *singletonContext) OtherModulePropertyErrorf(logicModule Module, property string, format string,
	args ...interface{}) {

	s.error(s.context.PropertyErrorf(logicModule, property, format, args...))
}

func (s *singletonContext) Failed() bool {
	return len(s.errs) > 0
}

func (s *singletonContext) Variable(pctx PackageContext, name, value string) {
	s.scope.ReparentTo(pctx)

	v, err := s.scope.AddLocalVariable(name, value)
	if err != nil {
		panic(err)
	}

	s.actionDefs.variables = append(s.actionDefs.variables, v)
}

func (s *singletonContext) Rule(pctx PackageContext, name string,
	params RuleParams, argNames ...string) Rule {

	s.scope.ReparentTo(pctx)

	r, err := s.scope.AddLocalRule(name, &params, argNames...)
	if err != nil {
		panic(err)
	}

	s.actionDefs.rules = append(s.actionDefs.rules, r)

	return r
}

func (s *singletonContext) Build(pctx PackageContext, params BuildParams) {
	s.scope.ReparentTo(pctx)

	def, err := parseBuildParams(s.scope, &params, map[string]string{
		"module_name": s.name,
		"module_type": "singleton",
	})
	if err != nil {
		panic(err)
	}

	s.actionDefs.buildDefs = append(s.actionDefs.buildDefs, def)
}

func (s *singletonContext) Eval(pctx PackageContext, str string) (string, error) {
	s.scope.ReparentTo(pctx)

	ninjaStr, err := parseNinjaString(s.scope, str)
	if err != nil {
		return "", err
	}

	err = s.globals.addNinjaStringDeps(ninjaStr)
	if err != nil {
		return "", err
	}

	return s.globals.Eval(ninjaStr)
}

func (s *singletonContext) RequireNinjaVersion(major, minor, micro int) {
	s.context.requireNinjaVersion(major, minor, micro)
}

func (s *singletonContext) SetOutDir(pctx PackageContext, value string) {
	s.scope.ReparentTo(pctx)

	ninjaValue, err := parseNinjaString(s.scope, value)
	if err != nil {
		panic(err)
	}

	s.context.setOutDir(ninjaValue)
}

func (s *singletonContext) AddSubninja(file string) {
	s.context.subninjas = append(s.context.subninjas, file)
}

func (s *singletonContext) VisitAllModules(visit func(Module)) {
	var visitingModule Module
	defer func() {
		if r := recover(); r != nil {
			panic(newPanicErrorf(r, "VisitAllModules(%s) for module %s",
				funcName(visit), s.context.moduleInfo[visitingModule]))
		}
	}()

	s.context.VisitAllModules(func(m Module) {
		visitingModule = m
		visit(m)
	})
}

func (s *singletonContext) VisitAllModuleProxies(visit func(proxy ModuleProxy)) {
	s.VisitAllModules(visitProxyAdaptor(visit))
}

func (s *singletonContext) VisitAllModulesIf(pred func(Module) bool,
	visit func(Module)) {

	s.context.VisitAllModulesIf(pred, visit)
}

func (s *singletonContext) VisitDirectDeps(module Module, visit func(Module)) {
	s.context.VisitDirectDeps(module, visit)
}

func (s *singletonContext) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
	s.context.VisitDirectDepsIf(module, pred, visit)
}

func (s *singletonContext) VisitDepsDepthFirst(module Module,
	visit func(Module)) {

	s.context.VisitDepsDepthFirst(module, visit)
}

func (s *singletonContext) VisitDepsDepthFirstIf(module Module,
	pred func(Module) bool, visit func(Module)) {

	s.context.VisitDepsDepthFirstIf(module, pred, visit)
}

func (s *singletonContext) PrimaryModule(module Module) Module {
	return s.context.PrimaryModule(module)
}

func (s *singletonContext) IsFinalModule(module Module) bool {
	return s.context.IsFinalModule(module)
}

func (s *singletonContext) VisitAllModuleVariants(module Module, visit func(Module)) {
	s.context.VisitAllModuleVariants(module, visit)
}

func (s *singletonContext) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) {
	s.context.VisitAllModuleVariants(module, visitProxyAdaptor(visit))
}

func (s *singletonContext) AddNinjaFileDeps(deps ...string) {
	s.ninjaFileDeps = append(s.ninjaFileDeps, deps...)
}

func (s *singletonContext) GlobWithDeps(pattern string,
	excludes []string) ([]string, error) {
	return s.context.glob(pattern, excludes)
}

func (s *singletonContext) Fs() pathtools.FileSystem {
	return s.context.fs
}

func (s *singletonContext) ModuleVariantsFromName(referer Module, name string) []Module {
	c := s.context

	refererInfo := c.moduleInfo[referer]
	if refererInfo == nil {
		s.ModuleErrorf(referer, "could not find module %q", referer.Name())
		return nil
	}

	moduleGroup, exists := c.nameInterface.ModuleFromName(name, refererInfo.namespace())
	if !exists {
		return nil
	}
	result := make([]Module, 0, len(moduleGroup.modules))
	for _, moduleInfo := range moduleGroup.modules {
		result = append(result, moduleInfo.logicModule)
	}
	return result
}

func (s *singletonContext) HasMutatorFinished(mutatorName string) bool {
	return s.context.HasMutatorFinished(mutatorName)
}

func visitProxyAdaptor(visit func(proxy ModuleProxy)) func(module Module) {
	return func(module Module) {
		visit(ModuleProxy{
			module: module,
		})
	}
}
