/**
 * 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 (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/util"
)

func (t *TargetBuilder) loadLoader(slot int, extraJtagCmd string, imgFilename string) error {
	if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	return t.LoaderBuilder.Load(slot, extraJtagCmd, imgFilename)
}

func (t *TargetBuilder) loadApp(slot int, extraJtagCmd string, imgFilename string) error {
	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	return t.AppBuilder.Load(slot, extraJtagCmd, imgFilename)
}

func (t *TargetBuilder) debugLoader(extraJtagCmd string, reset bool,
	noGDB bool, elfBase string) error {

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

	return t.LoaderBuilder.Debug(extraJtagCmd, reset, noGDB, elfBase)
}

func (t *TargetBuilder) debugApp(extraJtagCmd string, reset bool,
	noGDB bool, elfBase string) error {

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

	return t.AppBuilder.Debug(extraJtagCmd, reset, noGDB, elfBase)
}

// Load loads a .img file onto a device.  If imgFileOverride is not empty, it
// specifies the path of the image file to load.  If it is empty, the image in
// the target's `bin` directory is loaded.
func (t *TargetBuilder) Load(extraJtagCmd string, imgFileOverride string) error {
	err := t.PrepBuild()
	if err != nil {
		return err
	}

	if t.LoaderBuilder != nil && imgFileOverride != "" {
		return util.FmtNewtError(
			"cannot specify image file override for split images")
	}

	appImg := imgFileOverride
	if appImg == "" {
		appImg = t.AppBuilder.AppBinBasePath()
	}

	if t.LoaderBuilder != nil {
		err = t.loadApp(1, extraJtagCmd, appImg)
		if err == nil {
			err = t.loadLoader(0, extraJtagCmd, t.LoaderBuilder.AppBinBasePath())
		}
	} else {
		err = t.loadApp(0, extraJtagCmd, appImg)
	}

	return err
}

func RunOptionalCheck(checkScript string, env map[string]string) error {
	if checkScript == "" {
		return nil
	}

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGTERM)

	cmd := []string{
		checkScript,
	}

	/* Handle Ctrl-C, terminate newt, as it is the
	   intended behavior */
	go func() {
		sig := <-sigs
		fmt.Println(sig)
		os.Exit(0)
	}()

	util.StatusMessage(util.VERBOSITY_SILENT,
		"Optional target check: %s\n", strings.Join(cmd, " "))
	util.ShellInteractiveCommand(cmd, env, true)

	/* Unregister SIGTERM handler */
	signal.Reset(syscall.SIGTERM)
	return nil
}

func Load(binBasePath string, bspPkg *pkg.BspPackage,
	extraEnvSettings map[string]string) error {

	if bspPkg.DownloadScript == "" {
		return nil
	}

	env := BasicEnvVars(binBasePath, bspPkg)
	for k, v := range extraEnvSettings {
		env[k] = v
	}

	RunOptionalCheck(bspPkg.OptChkScript, env)
	// bspPath, binBasePath are passed in command line for backwards
	// compatibility
	cmd := []string{
		bspPkg.DownloadScript,
		bspPkg.BasePath(),
		binBasePath,
	}

	util.StatusMessage(util.VERBOSITY_VERBOSE, "Load command: %s\n",
		strings.Join(cmd, " "))
	util.StatusMessage(util.VERBOSITY_VERBOSE, "Environment:\n")
	for _, v := range env {
		util.StatusMessage(util.VERBOSITY_VERBOSE, "* %s\n", v)
	}
	if _, err := util.ShellCommand(cmd, env); err != nil {
		return err
	}
	util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")

	return nil
}

func (b *Builder) Load(imageSlot int, extraJtagCmd string, imgFilename string) error {
	if b.appPkg == nil {
		return util.NewNewtError("app package not specified")
	}

	/* Populate the package list and feature sets. */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	env, err := b.EnvVars(imageSlot)
	if err != nil {
		return err
	}

	if extraJtagCmd != "" {
		env["EXTRA_JTAG_CMD"] = extraJtagCmd
	}

	if _, ok := env["BOOT_LOADER"]; ok {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading bootloader (%s)\n", imgFilename)
	} else {
		util.StatusMessage(util.VERBOSITY_DEFAULT,
			"Loading %s image into slot %d (%s)\n", b.buildName, imageSlot+1, imgFilename)
	}

	// Convert the binary path from absolute to relative.  This is required for
	// compatibility with unix-in-windows environemnts (e.g., cygwin).
	binPath := util.TryRelPath(imgFilename)

	if err := Load(binPath, b.targetBuilder.bspPkg, env); err != nil {
		return err
	}

	return nil
}

// Debug runs gdb on the .elf file corresponding to what is running on a
// device.  If elfFileOverride is not empty, it specifies the path of the .elf
// file to debug.  If it is empty, the .elf file in the target's `bin`
// directory is loaded.
func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool, noGDB bool, elfFileOverride string) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	var elfBase string // Everything except ".elf"

	if elfFileOverride != "" {
		// The debug script appends ".elf" to the basename.  Make sure we can strip
		// the extension here and the script will reconstruct the original
		// filename.
		elfBase = strings.TrimSuffix(elfFileOverride, ".elf")
		if elfBase == elfFileOverride {
			return util.FmtNewtError(
				"invalid elf filename: must end in \".elf\": filename=%s",
				elfFileOverride)
		}
	}

	if t.LoaderBuilder == nil {
		if elfBase == "" {
			elfBase = t.AppBuilder.AppBinBasePath()
		}
		return t.debugApp(extraJtagCmd, reset, noGDB, elfBase)
	} else {
		if elfBase == "" {
			elfBase = t.LoaderBuilder.AppBinBasePath()
		}
		return t.debugLoader(extraJtagCmd, reset, noGDB, elfBase)
	}
}

func (b *Builder) debugBin(binPath string, extraJtagCmd string, reset bool,
	noGDB bool) error {
	/*
	 * Populate the package list and feature sets.
	 */
	err := b.targetBuilder.PrepBuild()
	if err != nil {
		return err
	}

	bspPath := b.bspPkg.rpkg.Lpkg.BasePath()
	binBasePath := binPath
	bspPkg := b.targetBuilder.bspPkg

	env, err := b.EnvVars(0)
	if err != nil {
		return err
	}

	// Make sure the elf override (if any) gets used.
	env["BIN_BASENAME"] = binPath

	if extraJtagCmd != "" {
		env["EXTRA_JTAG_CMD"] = extraJtagCmd
	}
	if reset == true {
		env["RESET"] = "true"
	}
	if noGDB == true {
		env["NO_GDB"] = "1"
	}

	os.Chdir(project.GetProject().Path())

	RunOptionalCheck(bspPkg.OptChkScript, env)
	// bspPath, binBasePath are passed in command line for backwards
	// compatibility
	cmdLine := []string{
		b.targetBuilder.bspPkg.DebugScript, bspPath, binBasePath,
	}

	fmt.Printf("%s\n", cmdLine)
	return util.ShellInteractiveCommand(cmdLine, env, false)
}

func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool, binBase string) error {
	return b.debugBin(binBase, extraJtagCmd, reset, noGDB)
}
