// 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 cc

import (
	"fmt"

	"android/soong/android"
	"os"
	"path"
	"path/filepath"
	"strings"
)

// This singleton generates CMakeLists.txt files. It does so for each blueprint Android.bp resulting in a cc.Module
// when either make, mm, mma, mmm or mmma is called. CMakeLists.txt files are generated in a separate folder
// structure (see variable CLionOutputProjectsDirectory for root).

func init() {
	android.RegisterSingletonType("cmakelists_generator", cMakeListsGeneratorSingleton)
}

func cMakeListsGeneratorSingleton() android.Singleton {
	return &cmakelistsGeneratorSingleton{}
}

type cmakelistsGeneratorSingleton struct{}

const (
	cMakeListsFilename              = "CMakeLists.txt"
	cLionAggregateProjectsDirectory = "development" + string(os.PathSeparator) + "ide" + string(os.PathSeparator) + "clion"
	cLionOutputProjectsDirectory    = "out" + string(os.PathSeparator) + cLionAggregateProjectsDirectory
	minimumCMakeVersionSupported    = "3.5"

	// Environment variables used to modify behavior of this singleton.
	envVariableGenerateCMakeLists = "SOONG_GEN_CMAKEFILES"
	envVariableGenerateDebugInfo  = "SOONG_GEN_CMAKEFILES_DEBUG"
	envVariableTrue               = "1"
)

// Instruct generator to trace how header include path and flags were generated.
// This is done to ease investigating bug reports.
var outputDebugInfo = false

func (c *cmakelistsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
	if getEnvVariable(envVariableGenerateCMakeLists, ctx) != envVariableTrue {
		return
	}

	outputDebugInfo = (getEnvVariable(envVariableGenerateDebugInfo, ctx) == envVariableTrue)

	// Track which projects have already had CMakeLists.txt generated to keep the first
	// variant for each project.
	seenProjects := map[string]bool{}

	ctx.VisitAllModules(func(module android.Module) {
		if ccModule, ok := module.(*Module); ok {
			if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
				generateCLionProject(compiledModule, ctx, ccModule, seenProjects)
			}
		}
	})

	// Link all handmade CMakeLists.txt aggregate from
	//     BASE/development/ide/clion to
	// BASE/out/development/ide/clion.
	dir := filepath.Join(android.AbsSrcDirForExistingUseCases(), cLionAggregateProjectsDirectory)
	filepath.Walk(dir, linkAggregateCMakeListsFiles)

	return
}

func getEnvVariable(name string, ctx android.SingletonContext) string {
	// Using android.Config.Getenv instead of os.getEnv to guarantee soong will
	// re-run in case this environment variable changes.
	return ctx.Config().Getenv(name)
}

func exists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return true
}

func linkAggregateCMakeListsFiles(path string, info os.FileInfo, err error) error {

	if info == nil {
		return nil
	}

	dst := strings.Replace(path, cLionAggregateProjectsDirectory, cLionOutputProjectsDirectory, 1)
	if info.IsDir() {
		// This is a directory to create
		os.MkdirAll(dst, os.ModePerm)
	} else {
		// This is a file to link
		os.Remove(dst)
		os.Symlink(path, dst)
	}
	return nil
}

func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module,
	seenProjects map[string]bool) {
	srcs := compiledModule.Srcs()
	if len(srcs) == 0 {
		return
	}

	// Only write CMakeLists.txt for the first variant of each architecture of each module
	clionprojectLocation := getCMakeListsForModule(ccModule, ctx)
	if seenProjects[clionprojectLocation] {
		return
	}

	seenProjects[clionprojectLocation] = true

	// Ensure the directory hosting the cmakelists.txt exists
	projectDir := path.Dir(clionprojectLocation)
	os.MkdirAll(projectDir, os.ModePerm)

	// Create cmakelists.txt
	f, _ := os.Create(filepath.Join(projectDir, cMakeListsFilename))
	defer f.Close()

	// Header.
	f.WriteString("# THIS FILE WAS AUTOMATICALY GENERATED!\n")
	f.WriteString("# ANY MODIFICATION WILL BE OVERWRITTEN!\n\n")
	f.WriteString("# To improve project view in Clion    :\n")
	f.WriteString("# Tools > CMake > Change Project Root  \n\n")
	f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported))
	f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
	f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", android.AbsSrcDirForExistingUseCases()))

	pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
	f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
	f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))

	// Add all sources to the project.
	f.WriteString("list(APPEND\n")
	f.WriteString("     SOURCE_FILES\n")
	for _, src := range srcs {
		f.WriteString(fmt.Sprintf("    ${ANDROID_ROOT}/%s\n", src.String()))
	}
	f.WriteString(")\n")

	// Add all header search path and compiler parameters (-D, -W, -f, -XXXX)
	f.WriteString("\n# GLOBAL ALL FLAGS:\n")
	globalAllParameters := parseCompilerParameters(ccModule.flags.Global.CommonFlags, ctx, f)
	translateToCMake(globalAllParameters, f, true, true)

	f.WriteString("\n# LOCAL ALL FLAGS:\n")
	localAllParameters := parseCompilerParameters(ccModule.flags.Local.CommonFlags, ctx, f)
	translateToCMake(localAllParameters, f, true, true)

	f.WriteString("\n# GLOBAL CFLAGS:\n")
	globalCParameters := parseCompilerParameters(ccModule.flags.Global.CFlags, ctx, f)
	translateToCMake(globalCParameters, f, true, true)

	f.WriteString("\n# LOCAL CFLAGS:\n")
	localCParameters := parseCompilerParameters(ccModule.flags.Local.CFlags, ctx, f)
	translateToCMake(localCParameters, f, true, true)

	f.WriteString("\n# GLOBAL C ONLY FLAGS:\n")
	globalConlyParameters := parseCompilerParameters(ccModule.flags.Global.ConlyFlags, ctx, f)
	translateToCMake(globalConlyParameters, f, true, false)

	f.WriteString("\n# LOCAL C ONLY FLAGS:\n")
	localConlyParameters := parseCompilerParameters(ccModule.flags.Local.ConlyFlags, ctx, f)
	translateToCMake(localConlyParameters, f, true, false)

	f.WriteString("\n# GLOBAL CPP FLAGS:\n")
	globalCppParameters := parseCompilerParameters(ccModule.flags.Global.CppFlags, ctx, f)
	translateToCMake(globalCppParameters, f, false, true)

	f.WriteString("\n# LOCAL CPP FLAGS:\n")
	localCppParameters := parseCompilerParameters(ccModule.flags.Local.CppFlags, ctx, f)
	translateToCMake(localCppParameters, f, false, true)

	f.WriteString("\n# GLOBAL SYSTEM INCLUDE FLAGS:\n")
	globalIncludeParameters := parseCompilerParameters(ccModule.flags.SystemIncludeFlags, ctx, f)
	translateToCMake(globalIncludeParameters, f, true, true)

	// Add project executable.
	f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n",
		cleanExecutableName(ccModule.ModuleBase.Name())))
}

func cleanExecutableName(s string) string {
	return strings.Replace(s, "@", "-", -1)
}

func translateToCMake(c compilerParameters, f *os.File, cflags bool, cppflags bool) {
	writeAllIncludeDirectories(c.systemHeaderSearchPath, f, true)
	writeAllIncludeDirectories(c.headerSearchPath, f, false)
	if cflags {
		writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_C_FLAGS")
		writeAllFlags(c.flags, f, "CMAKE_C_FLAGS")
	}
	if cppflags {
		writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_CXX_FLAGS")
		writeAllFlags(c.flags, f, "CMAKE_CXX_FLAGS")
	}
	if c.sysroot != "" {
		f.WriteString(fmt.Sprintf("include_directories(SYSTEM \"%s\")\n", buildCMakePath(path.Join(c.sysroot, "usr", "include"))))
	}

}

func buildCMakePath(p string) string {
	if path.IsAbs(p) {
		return p
	}
	return fmt.Sprintf("${ANDROID_ROOT}/%s", p)
}

func writeAllIncludeDirectories(includes []string, f *os.File, isSystem bool) {
	if len(includes) == 0 {
		return
	}

	system := ""
	if isSystem {
		system = "SYSTEM"
	}

	f.WriteString(fmt.Sprintf("include_directories(%s \n", system))

	for _, include := range includes {
		f.WriteString(fmt.Sprintf("    \"%s\"\n", buildCMakePath(include)))
	}
	f.WriteString(")\n\n")

	// Also add all headers to source files.
	f.WriteString("file (GLOB_RECURSE TMP_HEADERS\n")
	for _, include := range includes {
		f.WriteString(fmt.Sprintf("    \"%s/**/*.h\"\n", buildCMakePath(include)))
	}
	f.WriteString(")\n")
	f.WriteString("list (APPEND SOURCE_FILES ${TMP_HEADERS})\n\n")
}

type relativeFilePathFlagType struct {
	flag             string
	relativeFilePath string
}

func writeAllRelativeFilePathFlags(relativeFilePathFlags []relativeFilePathFlagType, f *os.File, tag string) {
	for _, flag := range relativeFilePathFlags {
		f.WriteString(fmt.Sprintf("set(%s \"${%s} %s=%s\")\n", tag, tag, flag.flag, buildCMakePath(flag.relativeFilePath)))
	}
}

func writeAllFlags(flags []string, f *os.File, tag string) {
	for _, flag := range flags {
		f.WriteString(fmt.Sprintf("set(%s \"${%s} %s\")\n", tag, tag, flag))
	}
}

type parameterType int

const (
	headerSearchPath parameterType = iota
	variable
	systemHeaderSearchPath
	flag
	systemRoot
	relativeFilePathFlag
)

type compilerParameters struct {
	headerSearchPath       []string
	systemHeaderSearchPath []string
	flags                  []string
	sysroot                string
	// Must be in a=b/c/d format and can be split into "a" and "b/c/d"
	relativeFilePathFlags []relativeFilePathFlagType
}

func makeCompilerParameters() compilerParameters {
	return compilerParameters{
		sysroot: "",
	}
}

func categorizeParameter(parameter string) parameterType {
	if strings.HasPrefix(parameter, "-I") {
		return headerSearchPath
	}
	if strings.HasPrefix(parameter, "$") {
		return variable
	}
	if strings.HasPrefix(parameter, "-isystem") {
		return systemHeaderSearchPath
	}
	if strings.HasPrefix(parameter, "-isysroot") {
		return systemRoot
	}
	if strings.HasPrefix(parameter, "--sysroot") {
		return systemRoot
	}
	if strings.HasPrefix(parameter, "-fsanitize-blacklist") {
		return relativeFilePathFlag
	}
	if strings.HasPrefix(parameter, "-fprofile-sample-use") {
		return relativeFilePathFlag
	}
	return flag
}

// Flattens a list of strings potentially containing space characters into a list of string containing no
// spaces.
func normalizeParameters(params []string) []string {
	var flatParams []string
	for _, s := range params {
		s = strings.Trim(s, " ")
		if len(s) == 0 {
			continue
		}
		flatParams = append(flatParams, strings.Split(s, " ")...)
	}
	return flatParams
}

func parseCompilerParameters(params []string, ctx android.SingletonContext, f *os.File) compilerParameters {
	var compilerParameters = makeCompilerParameters()

	for i, str := range params {
		f.WriteString(fmt.Sprintf("# Raw param [%d] = '%s'\n", i, str))
	}

	// Soong does not guarantee that each flag will be in an individual string. e.g: The
	// input received could be:
	// params = {"-isystem", "path/to/system"}
	// or it could be
	// params = {"-isystem path/to/system"}
	// To normalize the input, we split all strings with the "space" character and consolidate
	// all tokens into a flattened parameters list
	params = normalizeParameters(params)

	for i := 0; i < len(params); i++ {
		param := params[i]
		if param == "" {
			continue
		}

		switch categorizeParameter(param) {
		case headerSearchPath:
			compilerParameters.headerSearchPath =
				append(compilerParameters.headerSearchPath, strings.TrimPrefix(param, "-I"))
		case variable:
			if evaluated, error := evalVariable(ctx, param); error == nil {
				if outputDebugInfo {
					f.WriteString(fmt.Sprintf("# variable %s = '%s'\n", param, evaluated))
				}

				paramsFromVar := parseCompilerParameters(strings.Split(evaluated, " "), ctx, f)
				concatenateParams(&compilerParameters, paramsFromVar)

			} else {
				if outputDebugInfo {
					f.WriteString(fmt.Sprintf("# variable %s could NOT BE RESOLVED\n", param))
				}
			}
		case systemHeaderSearchPath:
			if i < len(params)-1 {
				compilerParameters.systemHeaderSearchPath =
					append(compilerParameters.systemHeaderSearchPath, params[i+1])
			} else if outputDebugInfo {
				f.WriteString("# Found a header search path marker with no path")
			}
			i = i + 1
		case flag:
			c := cleanupParameter(param)
			f.WriteString(fmt.Sprintf("# FLAG '%s' became %s\n", param, c))
			compilerParameters.flags = append(compilerParameters.flags, c)
		case systemRoot:
			if i < len(params)-1 {
				compilerParameters.sysroot = params[i+1]
			} else if outputDebugInfo {
				f.WriteString("# Found a system root path marker with no path")
			}
			i = i + 1
		case relativeFilePathFlag:
			flagComponents := strings.Split(param, "=")
			if len(flagComponents) == 2 {
				flagStruct := relativeFilePathFlagType{flag: flagComponents[0], relativeFilePath: flagComponents[1]}
				compilerParameters.relativeFilePathFlags = append(compilerParameters.relativeFilePathFlags, flagStruct)
			} else {
				if outputDebugInfo {
					f.WriteString(fmt.Sprintf("# Relative File Path Flag [%s] is not formatted as a=b/c/d \n", param))
				}
			}
		}
	}
	return compilerParameters
}

func cleanupParameter(p string) string {
	// In the blueprint, c flags can be passed as:
	//  cflags: [ "-DLOG_TAG=\"libEGL\"", ]
	// which becomes:
	// '-DLOG_TAG="libEGL"' in soong.
	// In order to be injected in CMakelists.txt we need to:
	// - Remove the wrapping ' character
	// - Double escape all special \ and " characters.
	// For a end result like:
	// -DLOG_TAG=\\\"libEGL\\\"
	if !strings.HasPrefix(p, "'") || !strings.HasSuffix(p, "'") || len(p) < 3 {
		return p
	}

	// Reverse wrapper quotes and escaping that may have happened in NinjaAndShellEscape
	// TODO:  It is ok to reverse here for now but if NinjaAndShellEscape becomes more complex,
	// we should create a method NinjaAndShellUnescape in escape.go and use that instead.
	p = p[1 : len(p)-1]
	p = strings.Replace(p, `'\''`, `'`, -1)
	p = strings.Replace(p, `$$`, `$`, -1)

	p = doubleEscape(p)
	return p
}

func escape(s string) string {
	s = strings.Replace(s, `\`, `\\`, -1)
	s = strings.Replace(s, `"`, `\"`, -1)
	return s
}

func doubleEscape(s string) string {
	s = escape(s)
	s = escape(s)
	return s
}

func concatenateParams(c1 *compilerParameters, c2 compilerParameters) {
	c1.headerSearchPath = append(c1.headerSearchPath, c2.headerSearchPath...)
	c1.systemHeaderSearchPath = append(c1.systemHeaderSearchPath, c2.systemHeaderSearchPath...)
	if c2.sysroot != "" {
		c1.sysroot = c2.sysroot
	}
	c1.flags = append(c1.flags, c2.flags...)
}

func evalVariable(ctx android.SingletonContext, str string) (string, error) {
	evaluated, err := ctx.Eval(pctx, str)
	if err == nil {
		return evaluated, nil
	}
	return "", err
}

func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string {
	return filepath.Join(android.AbsSrcDirForExistingUseCases(),
		cLionOutputProjectsDirectory,
		path.Dir(ctx.BlueprintFile(module)),
		module.ModuleBase.Name()+"-"+
			module.ModuleBase.Arch().ArchType.Name+"-"+
			module.ModuleBase.Os().Name,
		cMakeListsFilename)
}
