/*
 Copyright 2015 Runtime Inc.
 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 cli

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

type Compiler struct {
	ConfigPath   string
	TargetName   string
	BaseIncludes []string
	ObjPathList  map[string]bool
	LinkerScript string

	Cflags string
	Aflags string
	Lflags string

	ccPath                string
	asPath                string
	arPath                string
	odPath                string
	osPath                string
	ocPath                string
	ldFlags               string
	ldResolveCircularDeps bool
	ldMapFile             bool
}

func NewCompiler(ccPath string, cDef string, tName string, includes []string) (
	*Compiler, error) {
	c := &Compiler{
		ConfigPath:   ccPath,
		TargetName:   tName,
		BaseIncludes: includes,
	}

	log.Printf("[INFO] Loading compiler %s, target %s, def %s", ccPath, tName, cDef)

	err := c.ReadSettings(cDef)
	if err != nil {
		return nil, err
	}

	c.ObjPathList = make(map[string]bool)

	return c, nil
}

func (c *Compiler) ReadSettings(cDef string) error {
	v, err := ReadConfig(c.ConfigPath, "compiler")
	if err != nil {
		return err
	}

	c.ccPath = v.GetString("compiler.path.cc")
	c.asPath = v.GetString("compiler.path.as")
	c.arPath = v.GetString("compiler.path.archive")
	c.odPath = v.GetString("compiler.path.objdump")
	c.osPath = v.GetString("compiler.path.objsize")
	c.ocPath = v.GetString("compiler.path.objcopy")

	cflags := v.GetStringSlice("compiler.flags." + cDef)
	for _, flag := range cflags {
		if strings.HasPrefix(flag, "compiler.flags") {
			c.Cflags += " " + strings.Trim(v.GetString(flag), "\n")
		} else {
			c.Cflags += " " + strings.Trim(flag, "\n")
		}
	}

	c.ldFlags = v.GetString("compiler.ld.flags")
	c.ldResolveCircularDeps = v.GetBool("compiler.ld.resolve_circular_deps")
	c.ldMapFile = v.GetBool("compiler.ld.mapfile")

	log.Printf("[INFO] ccPath = %s, arPath = %s, flags = %s", c.ccPath,
		c.arPath, c.Cflags)

	return nil
}

// file type 0 = cc, file type 1 = as
func (c *Compiler) CompileFile(file string, compilerType int) error {
	wd, _ := os.Getwd()
	objDir := wd + "/obj/" + c.TargetName + "/"

	if NodeNotExist(objDir) {
		os.MkdirAll(objDir, 0755)
	}

	objFile := strings.TrimSuffix(file, filepath.Ext(file)) + ".o"

	objPath := objDir + objFile
	c.ObjPathList[objPath] = true

	var cmd string

	switch compilerType {
	case 0:
		cmd = c.ccPath
	case 1:
		cmd = c.asPath
	default:
		return NewNewtError("Unknown compiler type")
	}

	cmd += " -c " + "-o " + objPath + " " + file +
		" " + c.Cflags + " -I" + strings.Join(c.BaseIncludes, " -I")

	_, err := ShellCommand(cmd)
	return err
}

func (c *Compiler) Compile(match string) error {
	files, _ := filepath.Glob(match)

	wd, err := os.Getwd()
	if err != nil {
		return err
	}

	log.Printf("[INFO] Compiling C (%s/%s) %s", wd, match, strings.Join(files, " "))

	for _, file := range files {
		err := c.CompileFile(file, 0)
		if err != nil {
			return err
		}
	}
	return nil
}

func (c *Compiler) CompileAs(match string) error {
	files, _ := filepath.Glob(match)

	wd, err := os.Getwd()
	if err != nil {
		return err
	}

	log.Printf("[INFO] Compiling assembly (%s/%s) %s", wd, match, strings.Join(files, " "))

	for _, file := range files {
		err := c.CompileFile(file, 1)
		if err != nil {
			return err
		}
	}

	return nil
}

func (c *Compiler) RecursiveClean(path string, tName string) error {
	// Find all the subdirectories of path that contain an "obj/" directory, and
	// remove that directory either altogether, or just the arch specific directory.
	dirList, err := ioutil.ReadDir(path)
	if err != nil {
		return NewNewtError(err.Error())
	}

	for _, node := range dirList {
		if node.IsDir() {
			if node.Name() == "obj" || node.Name() == "bin" {
				if tName == "" {
					os.RemoveAll(path + "/" + node.Name() + "/")
				} else {
					os.RemoveAll(path + "/" + node.Name() + "/" + tName + "/")
				}
			} else {
				// recurse into the directory.
				err = c.RecursiveClean(path+"/"+node.Name(), tName)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func (c *Compiler) processEntry(wd string, node os.FileInfo, match string, cType int,
	ignDirs []string) error {
	// check to see if we ignore this element
	for _, entry := range ignDirs {
		if entry == node.Name() {
			return nil
		}
	}

	// if not, recurse into the directory
	os.Chdir(wd + "/" + node.Name())
	return c.RecursiveCompile(match, cType, ignDirs)
}

func (c *Compiler) RecursiveCompile(match string, cType int, ignDirs []string) error {
	// Get a list of files in the current directory, and if they are a directory,
	// and that directory is not in the ignDirs variable, then recurse into that
	// directory and compile the files in there
	wd, err := os.Getwd()
	if err != nil {
		return NewNewtError(err.Error())
	}

	dirList, err := ioutil.ReadDir(wd)
	if err != nil {
		return NewNewtError(err.Error())
	}

	for _, node := range dirList {
		if node.IsDir() {
			err = c.processEntry(wd, node, match, cType, ignDirs)
			if err != nil {
				return err
			}
		}
	}

	os.Chdir(wd)

	switch cType {
	case 0:
		return c.Compile(match)
	case 1:
		return c.CompileAs(match)
	default:
		return NewNewtError("Wrong compiler type specified to RecursiveCompile")
	}
}

func (c *Compiler) getObjFiles(baseObjFiles string) string {
	objList := baseObjFiles
	for objName, _ := range c.ObjPathList {
		objList += " " + objName
	}
	return objList
}

func (c *Compiler) CompileBinary(dstFile string, options map[string]bool,
	objFiles string) error {
	objList := c.getObjFiles(objFiles)

	log.Printf("[INFO] Compiling Binary %s with object files %s", dstFile,
		objList)

	cmd := c.ccPath + " -o " + dstFile + " " + c.ldFlags + " " + c.Cflags
	if c.ldResolveCircularDeps {
		cmd += " -Wl,--start-group -lc " + objList + " -Wl,--end-group "
	} else {
		cmd += " " + objList
	}

	if c.LinkerScript != "" {
		cmd += " -T " + c.LinkerScript
	}
	if checkBoolMap(options, "mapFile") {
		cmd += " -Wl,-Map=" + dstFile + ".map"
	}

	_, err := ShellCommand(cmd)
	if err != nil {
		return err
	}

	if checkBoolMap(options, "listFile") {
		listFile := dstFile + ".lst"
		// if list file exists, remove it
		if NodeExist(listFile) {
			if err := os.RemoveAll(listFile); err != nil {
				return err
			}
		}

		cmd = c.odPath + " -wxdS " + dstFile + " >> " + listFile
		_, err := ShellCommand(cmd)
		if err != nil {
			// XXX: gobjdump appears to always crash.  Until we get that sorted
			// out, don't fail the link process if lst generation fails.
			return nil
		}

		sects := []string{".text", ".rodata", ".data"}
		for _, sect := range sects {
			cmd = c.odPath + " -s -j " + sect + " " + dstFile + " >> " + listFile
			ShellCommand(cmd)
		}

		cmd = c.osPath + " " + dstFile + " >> " + listFile
	}

	if checkBoolMap(options, "binFile") {
		binFile := dstFile + ".bin"
		cmd = c.ocPath + " -R .bss -R .bss.core -R .bss.core.nz -O binary " +
			dstFile + " " + binFile
		_, err := ShellCommand(cmd)
		if err != nil {
			return err
		}
	}

	return nil
}

func (c *Compiler) CompileElf(binFile string, options map[string]bool,
	objFiles string) error {
	binFile += ".elf"
	return c.CompileBinary(binFile, options, objFiles)
}

func (c *Compiler) CompileArchive(archiveFile string, objFiles string) error {
	objList := c.getObjFiles(objFiles)

	log.Printf("[INFO] Compiling archive %s with object files %s",
		archiveFile, objList)

	cmd := c.arPath + " rcs " + archiveFile + " " + objList

	_, err := ShellCommand(cmd)
	return err
}
