/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 builder

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"

	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

const CMAKELISTS_FILENAME string = "CMakeLists.txt"

func CmakeListsPath() string {
	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
}

func EscapeName(name string) string {
	return strings.Replace(name, "/", "_", -1)
}

func ExtractLibraryName(filepath string) string {
	_, name := path.Split(filepath)
	name = strings.TrimPrefix(name, "lib")
	name = strings.TrimSuffix(name, ".a")
	return name
}

func replaceBackslashes(path string) string {
	return strings.Replace(path, "\\", "/", -1)
}

func replaceBackslashesSlice(elements []string) {
	for e := range elements {
		elements[e] = replaceBackslashes(elements[e])
	}
}

func escapeFlags(flag string) string {
	flag = strings.Replace(flag, "\"", "\\\\\\\"", -1)
	flag = strings.Replace(flag, "(", "\\\\(", -1)
	flag = strings.Replace(flag, ")", "\\\\)", -1)
	return flag
}

func escapeFlagsSlice(flags []string) []string {
	for f := range flags {
		flags[f] = escapeFlags(flags[f])
	}

	return flags
}

func trimProjectPath(path string) string {
	proj := interfaces.GetProject()
	path = strings.TrimPrefix(path, proj.Path()+"/")
	return path
}

func trimProjectPathSlice(elements []string) {
	for e := range elements {
		elements[e] = trimProjectPath(elements[e])
	}
}

func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
	for _, f := range *flags {
		if strings.HasPrefix(f, "-I") {
			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
		} else {
			*other = append(*other, f)
		}
	}
}

func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob,
	includeDirs *[]string, linkFlags *[]string) {
	c := cj.Compiler

	flags := []string{}
	otherFlags := []string{}

	switch cj.CompilerType {
	case toolchain.COMPILER_TYPE_C:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
	case toolchain.COMPILER_TYPE_ASM:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().Aflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Aflags...)
	case toolchain.COMPILER_TYPE_CPP:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().CXXflags...)
		flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
	}

	*linkFlags = append(*linkFlags, c.GetCompilerInfo().Lflags...)
	*linkFlags = append(*linkFlags, c.GetLocalCompilerInfo().Lflags...)

	extractIncludes(&flags, includeDirs, &otherFlags)
	cj.Filename = trimProjectPath(cj.Filename)

	// Sort and remove duplicate flags
	otherFlags = util.SortFields(otherFlags...)

	fmt.Fprintf(w,
`set_property(SOURCE %s APPEND_STRING
             PROPERTY COMPILE_FLAGS
             "%s")`,
		cj.Filename,
		strings.Join(escapeFlagsSlice(otherFlags), " "))
	fmt.Fprintln(w)
}

func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage,
	linkFlags *[]string, libraries *[]string) (*BuildPackage, error) {
	entries, err := b.collectCompileEntriesBpkg(bpkg)
	if err != nil {
		return nil, err
	}

	if len(entries) <= 0 {
		return nil, nil
	}

	otherIncludes := []string{}
	files := []string{}
	linkDirs := []string{}

	for _, s := range entries {
		filename := filepath.ToSlash(s.Filename)
		if s.Compiler.ShouldIgnoreFile(filename) {
			log.Infof("Ignoring %s because package dictates it.\n", filename)
			continue
		}

		if s.CompilerType == toolchain.COMPILER_TYPE_ARCHIVE {
			arFile := trimProjectPath(s.Filename)
			linkDirs = append(linkDirs, filepath.Dir(arFile))
			*libraries = append(*libraries, arFile)
		} else {
			CmakeSourceObjectWrite(w, s, &otherIncludes, linkFlags)
			s.Filename = trimProjectPath(s.Filename)
			files = append(files, s.Filename)
		}
	}

	if len(linkDirs) > 0 {
		replaceBackslashesSlice(linkDirs)
		fmt.Fprintf(w, "link_directories(%s)\n", strings.Join(util.SortFields(linkDirs...), " "))
	}

	if len(files) <= 0 {
		return nil, nil
	}

	pkgName := bpkg.rpkg.Lpkg.Name()

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "\n# Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "add_library(%s %s)\n",
		EscapeName(pkgName),
		strings.Join(files, " "))
	archivePath := replaceBackslashes(trimProjectPath(filepath.Dir(b.ArchivePath(bpkg))))
	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)

	return bpkg, nil
}

func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	bpkgs := b.sortedBuildPackages()
	var compileFlags []string
	var linkFlags []string
	var libraries []string

	c := targetCompiler
	c.AddInfo(b.GetCompilerInfo())

	builtPackages := []*BuildPackage{}
	for _, bpkg := range bpkgs {
		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg,
			&linkFlags, &libraries)
		if err != nil {
			return err
		}

		if builtPackage != nil {
			builtPackages = append(builtPackages, builtPackage)
		}
	}

	elfName := "cmake_" + filepath.Base(b.AppElfPath())
	fmt.Fprintf(w, "# Generating code for %s\n", elfName)

	var targetObjectsBuffer bytes.Buffer

	for _, bpkg := range builtPackages {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			EscapeName(bpkg.rpkg.Lpkg.Name())))
	}

	for _, filename := range libraries {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			ExtractLibraryName(filename)))
	}

	elfOutputDir := replaceBackslashes(trimProjectPath(filepath.Dir(b.AppElfPath())))
	fmt.Fprintf(w, "file(WRITE %s \"\")\n", replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))
	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName,
		replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))

	if c.GetLdResolveCircularDeps() {
		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
			elfName, targetObjectsBuffer.String())
	} else {
		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
			elfName, targetObjectsBuffer.String())
	}

	compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
	compileFlags = util.SortFields(compileFlags...)

	fmt.Fprintf(w,
`set_property(TARGET %s APPEND_STRING
             PROPERTY
             COMPILE_FLAGS
             "%s")`,
		elfName,
		strings.Join(escapeFlagsSlice(compileFlags), " "))
	fmt.Fprintln(w)

	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
	lFlags = append(lFlags, linkFlags...)
	lFlags = util.SortFields(lFlags...)

	for _, ld := range c.LinkerScripts {
		lFlags = append(lFlags, "-T"+ld)
	}

	var cFlags []string
	cFlags = append(cFlags, c.GetCompilerInfo().Cflags...)
	cFlags = append(cFlags, c.GetLocalCompilerInfo().Cflags...)
	cFlags = util.SortFields(cFlags...)
	lFlags = append(lFlags, cFlags...)

	var cxxFlags []string
	cxxFlags = append(cxxFlags, c.GetCompilerInfo().CXXflags...)
	cxxFlags = append(cxxFlags, c.GetLocalCompilerInfo().CXXflags...)
	cxxFlags = util.SortFields(cxxFlags...)
	lFlags = append(lFlags, cxxFlags...)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s
                      LINK_FLAGS "%s"
                      LINKER_LANGUAGE C)`,
		elfName,
		elfOutputDir,
		elfOutputDir,
		elfOutputDir,
		strings.Join(escapeFlagsSlice(lFlags), " "))

	fmt.Fprintln(w)

	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
	fmt.Fprintln(w)

	return nil
}

func getLibsFromLinkerFlags(lflags []string) []string {
	libs := []string{}

	for _, flag := range lflags {
		if strings.HasPrefix(flag, "-l") {
			libs = append(libs, flag)
		}
	}

	return libs
}

func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
	cj toolchain.CompilerJob, otherIncludes []string) {
	c := cj.Compiler

	var includes []string

	includes = append(includes, c.GetCompilerInfo().Includes...)
	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
	includes = append(includes, otherIncludes...)

	// Sort and remove duplicate flags
	includes = util.SortFields(includes...)
	trimProjectPathSlice(includes)
	replaceBackslashesSlice(includes)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s)`,
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		archiveFile,
		archiveFile,
		archiveFile,
	)
	fmt.Fprintln(w)
	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		strings.Join(includes, " "))
}

func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	if len(t.res.PreBuildCmdCfg.StageFuncs) > 0 ||
		len(t.res.PreLinkCmdCfg.StageFuncs) > 0 ||
		len(t.res.PostLinkCmdCfg.StageFuncs) > 0 {

		util.OneTimeWarning(
			"custom commands not included in cmake output (unsupported)")
	}

	/* Build the Apps */
	project.ResetDeps(t.AppList)

	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts

	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
		return err
	}

	return nil
}

func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
	/* Since CMake 3 it is required to set a full path to the compiler */
	/* TODO: get rid of the prefix to /usr/bin */
	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
	/* TODO: cmake returns error on link */
	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
	fmt.Fprintln(w)
}

func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
	CmakeCompilerWrite(w, c)
	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
	fmt.Fprintln(w)
}

func CMakeTargetGenerate(target *target.Target) error {
	CmakeFileHandle, err := os.Create(CmakeListsPath())
	if err != nil {
		return util.ChildNewtError(err)
	}

	var b = bytes.Buffer{}
	w := bufio.NewWriter(&b)
	defer CmakeFileHandle.Close()

	targetBuilder, err := NewTargetBuilder(target)
	if err != nil {
		return err
	}

	targetCompiler, err := targetBuilder.NewCompiler("", "")
	if err != nil {
		return err
	}

	CmakeHeaderWrite(w, targetCompiler, target.ShortName())

	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
		return err
	}

	w.Flush()

	CmakeFileHandle.Write(b.Bytes())
	return nil
}
