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

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

// PackageContext is a wrapper for blueprint.PackageContext that adds
// some android-specific helper functions.
type PackageContext struct {
	blueprint.PackageContext
}

func NewPackageContext(pkgPath string) PackageContext {
	return PackageContext{blueprint.NewPackageContext(pkgPath)}
}

// configErrorWrapper can be used with Path functions when a Context is not
// available. A Config can be provided, and errors are stored as a list for
// later retrieval.
//
// The most common use here will be with VariableFunc, where only a config is
// provided, and an error should be returned.
type configErrorWrapper struct {
	pctx   PackageContext
	config Config
	errors []error
}

var _ PathContext = &configErrorWrapper{}
var _ errorfContext = &configErrorWrapper{}
var _ PackageVarContext = &configErrorWrapper{}
var _ PackagePoolContext = &configErrorWrapper{}
var _ PackageRuleContext = &configErrorWrapper{}

func (e *configErrorWrapper) Config() Config {
	return e.config
}
func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
	e.errors = append(e.errors, fmt.Errorf(format, args...))
}
func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
	e.pctx.AddNinjaFileDeps(deps...)
}

func (e *configErrorWrapper) Fs() pathtools.FileSystem {
	return nil
}

type PackageVarContext interface {
	PathContext
	errorfContext
}

type PackagePoolContext PackageVarContext
type PackageRuleContext PackageVarContext

// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
// argument to a PackageVarContext.
func (p PackageContext) VariableFunc(name string,
	f func(PackageVarContext) string) blueprint.Variable {

	return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
		ctx := &configErrorWrapper{p, config.(Config), nil}
		ret := f(ctx)
		if len(ctx.errors) > 0 {
			return "", ctx.errors[0]
		}
		return ret, nil
	})
}

// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
// argument to a Context that supports Config().
func (p PackageContext) PoolFunc(name string,
	f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {

	return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
		ctx := &configErrorWrapper{p, config.(Config), nil}
		params := f(ctx)
		if len(ctx.errors) > 0 {
			return params, ctx.errors[0]
		}
		return params, nil
	})
}

// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
// argument to a Context that supports Config(), and provides a default Pool if none is
// specified.
func (p PackageContext) RuleFunc(name string,
	f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {

	return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
		ctx := &configErrorWrapper{p, config.(Config), nil}
		params := f(ctx)
		if len(ctx.errors) > 0 {
			return params, ctx.errors[0]
		}
		if (ctx.Config().UseGoma() || ctx.Config().UseRBE()) && params.Pool == nil {
			// When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
			// goma/RBE, restrict jobs to the local parallelism value
			params.Pool = localPool
		}
		return params, nil
	}, argNames...)
}

// SourcePathVariable returns a Variable whose value is the source directory
// appended with the supplied path. It may only be called during a Go package's
// initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		p, err := safePathForSource(ctx, path)
		if err != nil {
			ctx.Errorf("%s", err.Error())
		}
		return p.String()
	})
}

// SourcePathsVariable returns a Variable whose value is the source directory
// appended with the supplied paths, joined with separator. It may only be
// called during a Go package's initialization - either from the init()
// function or as part of a package-scoped variable's initialization.
func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		var ret []string
		for _, path := range paths {
			p, err := safePathForSource(ctx, path)
			if err != nil {
				ctx.Errorf("%s", err.Error())
			}
			ret = append(ret, p.String())
		}
		return strings.Join(ret, separator)
	})
}

// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory
// appended with the supplied path, or the value of the given environment variable if it is set.
// The environment variable is not required to point to a path inside the source tree.
// It may only be called during a Go package's initialization - either from the init() function or
// as part of a package-scoped variable's initialization.
func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		p, err := safePathForSource(ctx, path)
		if err != nil {
			ctx.Errorf("%s", err.Error())
		}
		return ctx.Config().GetenvWithDefault(env, p.String())
	})
}

// HostBinToolVariable returns a Variable whose value is the path to a host tool
// in the bin directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		return p.HostBinToolPath(ctx, path).String()
	})
}

func (p PackageContext) HostBinToolPath(ctx PackageVarContext, path string) Path {
	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin", path)
}

// HostJNIToolVariable returns a Variable whose value is the path to a host tool
// in the lib directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		return p.HostJNIToolPath(ctx, path).String()
	})
}

func (p PackageContext) HostJNIToolPath(ctx PackageVarContext, path string) Path {
	ext := ".so"
	if runtime.GOOS == "darwin" {
		ext = ".dylib"
	}
	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "lib64", path+ext)
}

// HostJavaToolVariable returns a Variable whose value is the path to a host
// tool in the frameworks directory for host targets. It may only be called
// during a Go package's initialization - either from the init() function or as
// part of a package-scoped variable's initialization.
func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		return p.HostJavaToolPath(ctx, path).String()
	})
}

func (p PackageContext) HostJavaToolPath(ctx PackageVarContext, path string) Path {
	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", path)
}

// IntermediatesPathVariable returns a Variable whose value is the intermediate
// directory appended with the supplied path. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		return PathForIntermediates(ctx, path).String()
	})
}

// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
// list of present source paths prefixed with the supplied prefix. It may only
// be called during a Go package's initialization - either from the init()
// function or as part of a package-scoped variable's initialization.
func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
	name, prefix string, paths []string) blueprint.Variable {

	return p.VariableFunc(name, func(ctx PackageVarContext) string {
		paths := ExistentPathsForSources(ctx, paths)
		return JoinWithPrefix(paths.Strings(), prefix)
	})
}

// AndroidStaticRule is an alias for StaticRule.
func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
	argNames ...string) blueprint.Rule {
	return p.StaticRule(name, params, argNames...)
}

// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
	argNames ...string) blueprint.Rule {
	return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
		return params
	}, argNames...)
}

// RemoteRuleSupports selects if a AndroidRemoteStaticRule supports goma, RBE, or both.
type RemoteRuleSupports int

const (
	SUPPORTS_NONE = 0
	SUPPORTS_GOMA = 1 << iota
	SUPPORTS_RBE  = 1 << iota
	SUPPORTS_BOTH = SUPPORTS_GOMA | SUPPORTS_RBE
)

// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
// and the appropriate SUPPORTS_* flag is set.
func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
	argNames ...string) blueprint.Rule {

	return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
		ctx := &configErrorWrapper{p, config.(Config), nil}
		if ctx.Config().UseGoma() && supports&SUPPORTS_GOMA == 0 {
			// When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
			// local parallelism value
			params.Pool = localPool
		}

		if ctx.Config().UseRBE() && supports&SUPPORTS_RBE == 0 {
			// When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
			// local parallelism value
			params.Pool = localPool
		}

		return params, nil
	}, argNames...)
}
