// Copyright 2017 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 build

import (
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"android/soong/ui/metrics"
	"android/soong/ui/status"
)

var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_")

const katiBuildSuffix = ""
const katiCleanspecSuffix = "-cleanspec"
const katiPackageSuffix = "-package"

// genKatiSuffix creates a filename suffix for kati-generated files so that we
// can cache them based on their inputs. Such files include the generated Ninja
// files and env.sh environment variable setup files.
//
// The filename suffix should encode all common changes to Kati inputs.
// Currently that includes the TARGET_PRODUCT and kati-processed command line
// arguments.
func genKatiSuffix(ctx Context, config Config) {
	// Construct the base suffix.
	katiSuffix := "-" + config.TargetProduct()

	// Append kati arguments to the suffix.
	if args := config.KatiArgs(); len(args) > 0 {
		katiSuffix += "-" + spaceSlashReplacer.Replace(strings.Join(args, "_"))
	}

	// If the suffix is too long, replace it with a md5 hash and write a
	// file that contains the original suffix.
	if len(katiSuffix) > 64 {
		shortSuffix := "-" + fmt.Sprintf("%x", md5.Sum([]byte(katiSuffix)))
		config.SetKatiSuffix(shortSuffix)

		ctx.Verbosef("Kati ninja suffix too long: %q", katiSuffix)
		ctx.Verbosef("Replacing with: %q", shortSuffix)

		if err := ioutil.WriteFile(strings.TrimSuffix(config.KatiBuildNinjaFile(), "ninja")+"suf", []byte(katiSuffix), 0777); err != nil {
			ctx.Println("Error writing suffix file:", err)
		}
	} else {
		config.SetKatiSuffix(katiSuffix)
	}
}

// Base function to construct and run the Kati command line with additional
// arguments, and a custom function closure to mutate the environment Kati runs
// in.
func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) {
	executable := config.PrebuiltBuildTool("ckati")
	// cKati arguments.
	args = append([]string{
		// Instead of executing commands directly, generate a Ninja file.
		"--ninja",
		// Generate Ninja files in the output directory.
		"--ninja_dir=" + config.OutDir(),
		// Filename suffix of the generated Ninja file.
		"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
		// Remove common parts at the beginning of a Ninja file, like build_dir,
		// local_pool and _kati_always_build_. Allows Kati to be run multiple
		// times, with generated Ninja files combined in a single invocation
		// using 'include'.
		"--no_ninja_prelude",
		// Support declaring phony outputs in AOSP Ninja.
		"--use_ninja_phony_output",
		// Support declaring symlink outputs in AOSP Ninja.
		"--use_ninja_symlink_outputs",
		// Regenerate the Ninja file if environment inputs have changed. e.g.
		// CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some
		// $(shell ..) results.
		"--regen",
		// Skip '-include' directives starting with the specified path. Used to
		// ignore generated .mk files.
		"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
		// Detect the use of $(shell echo ...).
		"--detect_android_echo",
		// Colorful ANSI-based warning and error messages.
		"--color_warnings",
		// Generate all targets, not just the top level requested ones.
		"--gen_all_targets",
		// Use the built-in emulator of GNU find for better file finding
		// performance. Used with $(shell find ...).
		"--use_find_emulator",
		// Fail when the find emulator encounters problems.
		"--werror_find_emulator",
		// Do not provide any built-in rules.
		"--no_builtin_rules",
		// Fail when suffix rules are used.
		"--werror_suffix_rules",
		// Fail when a real target depends on a phony target.
		"--werror_real_to_phony",
		// Makes real_to_phony checks assume that any top-level or leaf
		// dependencies that does *not* have a '/' in it is a phony target.
		"--top_level_phony",
		// Fail when a phony target contains slashes.
		"--werror_phony_looks_real",
		// Fail when writing to a read-only directory.
		"--werror_writable",
		// Print Kati's internal statistics, such as the number of variables,
		// implicit/explicit/suffix rules, and so on.
		"--kati_stats",
	}, args...)

	// Generate a minimal Ninja file.
	//
	// Used for build_test and multiproduct_kati, which runs Kati several
	// hundred times for different configurations to test file generation logic.
	// These can result in generating Ninja files reaching ~1GB or more,
	// resulting in ~hundreds of GBs of writes.
	//
	// Since we don't care about executing the Ninja files in these test cases,
	// generating the Ninja file content wastes time, so skip writing any
	// information out with --empty_ninja_file.
	//
	// From https://github.com/google/kati/commit/87b8da7af2c8bea28b1d8ab17679453d859f96e5
	if config.Environment().IsEnvTrue("EMPTY_NINJA_FILE") {
		args = append(args, "--empty_ninja_file")
	}

	// Apply 'local_pool' to to all rules that don't specify a pool.
	if config.UseRemoteBuild() {
		args = append(args, "--default_pool=local_pool")
	}

	cmd := Command(ctx, config, "ckati", executable, args...)

	// Set up the nsjail sandbox.
	cmd.Sandbox = katiSandbox

	// Set up stdout and stderr.
	pipe, err := cmd.StdoutPipe()
	if err != nil {
		ctx.Fatalln("Error getting output pipe for ckati:", err)
	}
	cmd.Stderr = cmd.Stdout

	// Apply the caller's function closure to mutate the environment variables.
	envFunc(cmd.Environment)

	// Pass on various build environment metadata to Kati.
	if _, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok {
		username := "unknown"
		if u, err := user.Current(); err == nil {
			username = u.Username
		} else {
			ctx.Println("Failed to get current user:", err)
		}
		cmd.Environment.Set("BUILD_USERNAME", username)
	}

	if _, ok := cmd.Environment.Get("BUILD_HOSTNAME"); !ok {
		hostname, err := os.Hostname()
		if err != nil {
			ctx.Println("Failed to read hostname:", err)
			hostname = "unknown"
		}
		cmd.Environment.Set("BUILD_HOSTNAME", hostname)
	}

	cmd.StartOrFatal()
	// Set up the ToolStatus command line reader for Kati for a consistent UI
	// for the user.
	status.KatiReader(ctx.Status.StartTool(), pipe)
	cmd.WaitOrFatal()
}

func runKatiBuild(ctx Context, config Config) {
	ctx.BeginTrace(metrics.RunKati, "kati build")
	defer ctx.EndTrace()

	args := []string{
		// Mark the output directory as writable.
		"--writable", config.OutDir() + "/",
		// Fail when encountering implicit rules. e.g.
		// %.foo: %.bar
		//   cp $< $@
		"--werror_implicit_rules",
		// Entry point for the Kati Ninja file generation.
		"-f", "build/make/core/main.mk",
	}

	if !config.BuildBrokenDupRules() {
		// Fail when redefining / duplicating a target.
		args = append(args, "--werror_overriding_commands")
	}

	args = append(args, config.KatiArgs()...)

	args = append(args,
		// Location of the Make vars .mk file generated by Soong.
		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
		// Location of the Android.mk file generated by Soong. This
		// file contains Soong modules represented as Kati modules,
		// allowing Kati modules to depend on Soong modules.
		"SOONG_ANDROID_MK="+config.SoongAndroidMk(),
		// Directory containing outputs for the target device.
		"TARGET_DEVICE_DIR="+config.TargetDeviceDir(),
		// Directory containing .mk files for packaging purposes, such as
		// the dist.mk file, containing dist-for-goals data.
		"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())

	runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})

	// compress and dist the main build ninja file.
	distGzipFile(ctx, config, config.KatiBuildNinjaFile())

	// Cleanup steps.
	cleanCopyHeaders(ctx, config)
	// Skip the old installed file cleanup step for few non-full build goals as we don't create
	// an installed file list for them.
	if config.FullBuild() {
		cleanOldInstalledFiles(ctx, config)
	}
}

// Clean out obsolete header files on the disk that were *not copied* during the
// build with BUILD_COPY_HEADERS and LOCAL_COPY_HEADERS.
//
// These should be increasingly uncommon, as it's a deprecated feature and there
// isn't an equivalent feature in Soong.
func cleanCopyHeaders(ctx Context, config Config) {
	ctx.BeginTrace("clean", "clean copy headers")
	defer ctx.EndTrace()

	// Read and parse the list of copied headers from a file in the product
	// output directory.
	data, err := ioutil.ReadFile(filepath.Join(config.ProductOut(), ".copied_headers_list"))
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		ctx.Fatalf("Failed to read copied headers list: %v", err)
	}

	headers := strings.Fields(string(data))
	if len(headers) < 1 {
		ctx.Fatal("Failed to parse copied headers list: %q", string(data))
	}
	headerDir := headers[0]
	headers = headers[1:]

	// Walk the tree and remove any headers that are not in the list of copied
	// headers in the current build.
	filepath.Walk(headerDir,
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return nil
			}
			if info.IsDir() {
				return nil
			}
			if !inList(path, headers) {
				ctx.Printf("Removing obsolete header %q", path)
				if err := os.Remove(path); err != nil {
					ctx.Fatalf("Failed to remove obsolete header %q: %v", path, err)
				}
			}
			return nil
		})
}

// Clean out any previously installed files from the disk that are not installed
// in the current build.
func cleanOldInstalledFiles(ctx Context, config Config) {
	ctx.BeginTrace("clean", "clean old installed files")
	defer ctx.EndTrace()

	// We shouldn't be removing files from one side of the two-step asan builds
	var suffix string
	if v, ok := config.Environment().Get("SANITIZE_TARGET"); ok {
		if sanitize := strings.Fields(v); inList("address", sanitize) {
			suffix = "_asan"
		}
	}

	cleanOldFiles(ctx, config.ProductOut(), ".installable_files"+suffix)

	cleanOldFiles(ctx, config.HostOut(), ".installable_test_files")
}

// Generate the Ninja file containing the packaging command lines for the dist
// dir.
func runKatiPackage(ctx Context, config Config) {
	ctx.BeginTrace(metrics.RunKati, "kati package")
	defer ctx.EndTrace()

	args := []string{
		// Mark the dist dir as writable.
		"--writable", config.DistDir() + "/",
		// Fail when encountering implicit rules. e.g.
		"--werror_implicit_rules",
		// Fail when redefining / duplicating a target.
		"--werror_overriding_commands",
		// Entry point.
		"-f", "build/make/packaging/main.mk",
		// Directory containing .mk files for packaging purposes, such as
		// the dist.mk file, containing dist-for-goals data.
		"KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(),
	}

	// Run Kati against a restricted set of environment variables.
	runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) {
		env.Allow([]string{
			// Some generic basics
			"LANG",
			"LC_MESSAGES",
			"PATH",
			"PWD",
			"TMPDIR",

			// Tool configs
			"ASAN_SYMBOLIZER_PATH",
			"JAVA_HOME",
			"PYTHONDONTWRITEBYTECODE",

			// Build configuration
			"ANDROID_BUILD_SHELL",
			"DIST_DIR",
			"OUT_DIR",
		}...)

		if config.Dist() {
			env.Set("DIST", "true")
			env.Set("DIST_DIR", config.DistDir())
		}
	})

	// Compress and dist the packaging Ninja file.
	distGzipFile(ctx, config, config.KatiPackageNinjaFile())
}

// Run Kati on the cleanspec files to clean the build.
func runKatiCleanSpec(ctx Context, config Config) {
	ctx.BeginTrace(metrics.RunKati, "kati cleanspec")
	defer ctx.EndTrace()

	runKati(ctx, config, katiCleanspecSuffix, []string{
		// Fail when encountering implicit rules. e.g.
		"--werror_implicit_rules",
		// Fail when redefining / duplicating a target.
		"--werror_overriding_commands",
		// Entry point.
		"-f", "build/make/core/cleanbuild.mk",
		"SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
		"TARGET_DEVICE_DIR=" + config.TargetDeviceDir(),
	}, func(env *Environment) {})
}
