// Copyright 2019 The Android Open Source Project
//
// 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 rust

import (
	"fmt"
	"path/filepath"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/rust/config"
)

func getEdition(compiler *baseCompiler) string {
	return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
}

func getDenyWarnings(compiler *baseCompiler) bool {
	return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings)
}

func (compiler *baseCompiler) setNoStdlibs() {
	compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
}

func NewBaseCompiler(dir, dir64 string) *baseCompiler {
	return &baseCompiler{
		Properties: BaseCompilerProperties{},
		dir:        dir,
		dir64:      dir64,
	}
}

type BaseCompilerProperties struct {
	// whether to pass "-D warnings" to rustc. Defaults to true.
	Deny_warnings *bool

	// flags to pass to rustc
	Flags []string `android:"path,arch_variant"`

	// flags to pass to the linker
	Ld_flags []string `android:"path,arch_variant"`

	// list of rust rlib crate dependencies
	Rlibs []string `android:"arch_variant"`

	// list of rust dylib crate dependencies
	Dylibs []string `android:"arch_variant"`

	// list of rust proc_macro crate dependencies
	Proc_macros []string `android:"arch_variant"`

	// list of C shared library dependencies
	Shared_libs []string `android:"arch_variant"`

	// list of C static library dependencies
	Static_libs []string `android:"arch_variant"`

	// crate name, required for libraries. This must be the expected extern crate name used in source
	Crate_name string `android:"arch_variant"`

	// list of features to enable for this crate
	Features []string `android:"arch_variant"`

	// specific rust edition that should be used if the default version is not desired
	Edition *string `android:"arch_variant"`

	// sets name of the output
	Stem *string `android:"arch_variant"`

	// append to name of output
	Suffix *string `android:"arch_variant"`

	// install to a subdirectory of the default install path for the module
	Relative_install_path *string `android:"arch_variant"`

	// whether to suppress inclusion of standard crates - defaults to false
	No_stdlibs *bool
}

type baseCompiler struct {
	Properties    BaseCompilerProperties
	pathDeps      android.Paths
	rustFlagsDeps android.Paths
	linkFlagsDeps android.Paths
	flags         string
	linkFlags     string
	depFlags      []string
	linkDirs      []string
	edition       string
	src           android.Path //rustc takes a single src file

	// Install related
	dir      string
	dir64    string
	subDir   string
	relative string
	path     android.InstallPath
}

var _ compiler = (*baseCompiler)(nil)

func (compiler *baseCompiler) compilerProps() []interface{} {
	return []interface{}{&compiler.Properties}
}

func (compiler *baseCompiler) featuresToFlags(features []string) []string {
	flags := []string{}
	for _, feature := range features {
		flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
	}
	return flags
}

func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {

	if getDenyWarnings(compiler) {
		flags.RustFlags = append(flags.RustFlags, "-D warnings")
	}
	flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
	flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
	flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler))
	flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
	flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
	flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
	flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())

	if ctx.Host() && !ctx.Windows() {
		rpath_prefix := `\$$ORIGIN/`
		if ctx.Darwin() {
			rpath_prefix = "@loader_path/"
		}

		var rpath string
		if ctx.toolchain().Is64Bit() {
			rpath = "lib64"
		} else {
			rpath = "lib"
		}
		flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
		flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath)
	}

	return flags
}

func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
	panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
}

func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
	deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
	deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
	deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
	deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
	deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)

	if !Bool(compiler.Properties.No_stdlibs) {
		for _, stdlib := range config.Stdlibs {
			// If we're building for host, use the compiler's stdlibs
			if ctx.Host() {
				stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
			}

			// This check is technically insufficient - on the host, where
			// static linking is the default, if one of our static
			// dependencies uses a dynamic library, we need to dynamically
			// link the stdlib as well.
			if (len(deps.Dylibs) > 0) || (!ctx.Host()) {
				// Dynamically linked stdlib
				deps.Dylibs = append(deps.Dylibs, stdlib)
			}
		}
	}
	return deps
}

func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
	deps.SharedLibs = append(deps.SharedLibs, "liblog")
	deps.SharedLibs = append(deps.SharedLibs, "libc")
	deps.SharedLibs = append(deps.SharedLibs, "libm")
	deps.SharedLibs = append(deps.SharedLibs, "libdl")

	//TODO(b/141331117) libstd requires libgcc on Android
	deps.StaticLibs = append(deps.StaticLibs, "libgcc")

	return deps
}

func (compiler *baseCompiler) crateName() string {
	return compiler.Properties.Crate_name
}

func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath {
	dir := compiler.dir
	if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
		dir = compiler.dir64
	}
	if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
		dir = filepath.Join(dir, ctx.Arch().ArchType.String())
	}
	return android.PathForModuleInstall(ctx, dir, compiler.subDir,
		compiler.relativeInstallPath(), compiler.relative)
}

func (compiler *baseCompiler) install(ctx ModuleContext, file android.Path) {
	compiler.path = ctx.InstallFile(compiler.installDir(ctx), file.Base(), file)
}

func (compiler *baseCompiler) getStem(ctx ModuleContext) string {
	return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix)
}

func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string {
	stem := ctx.baseModuleName()
	if String(compiler.Properties.Stem) != "" {
		stem = String(compiler.Properties.Stem)
	}

	return stem
}

func (compiler *baseCompiler) relativeInstallPath() string {
	return String(compiler.Properties.Relative_install_path)
}

func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path {
	srcPaths := android.PathsForModuleSrc(ctx, srcs)
	if len(srcPaths) != 1 {
		ctx.PropertyErrorf("srcs", "srcs can only contain one path for rust modules")
	}
	return srcPaths[0]
}
