// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"code.google.com/p/go.tools/go/vcs"
)

// These variables are copied from the gobuilder's environment
// to the envv of its subprocesses.
var extraEnv = []string{
	"GOARM",

	// For Unix derivatives.
	"CC",
	"PATH",
	"TMPDIR",
	"USER",

	// For Plan 9.
	"objtype",
	"cputype",
	"path",
}

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOHOSTOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOHOSTARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
	}

	for _, k := range extraEnv {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if _, err := repo.Clone(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error cloning repository: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gofrontendpath := filepath.Join(workpath, "gofrontend")
	gccpath := filepath.Join(repo.Path, "gcc")
	gccgopath := filepath.Join(gccpath, "gcc", "go", "gofrontend")
	gcclibgopath := filepath.Join(gccpath, "libgo")

	// get a handle to SVN vcs.Cmd for pulling down GCC.
	svn := vcs.ByCmd("svn")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return svn.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	} else {
		// make sure to remove gccgopath and gcclibgopath before
		// updating the repo to avoid file clobbering.
		if err := os.RemoveAll(gccgopath); err != nil {
			return "", err
		}
		if err := os.RemoveAll(gcclibgopath); err != nil {
			return "", err
		}
	}
	if err := svn.Download(gccpath); err != nil {
		return "", err
	}

	// clone gofrontend repo at specified revision
	if _, err := repo.Clone(gofrontendpath, hash); err != nil {
		return "", err
	}

	// remove gccgopath and gcclibgopath before copying over gofrontend.
	if err := os.RemoveAll(gccgopath); err != nil {
		return "", err
	}
	if err := os.RemoveAll(gcclibgopath); err != nil {
		return "", err
	}

	// copy gofrontend and libgo to appropriate locations
	if err := copyDir(filepath.Join(gofrontendpath, "go"), gccgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/go to gcc/go/gofrontend: %s\n", err)
	}
	if err := copyDir(filepath.Join(gofrontendpath, "libgo"), gcclibgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/libgo to gcc/libgo: %s\n", err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	gccConfigCmd := []string{filepath.Join(gccpath, "configure"), "--enable-languages=c,c++,go", "--disable-bootstrap"}
	if _, err := runOutput(*cmdTimeout, envv, ioutil.Discard, gccobjdir, gccConfigCmd...); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %s", err)
	}

	// build gcc
	if _, err := runOutput(*buildTimeout, envv, ioutil.Discard, gccobjdir, "make"); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil
}

// copyDir copies the src directory into the dst
func copyDir(src, dst string) error {
	return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
		dstPath := strings.Replace(path, src, dst, 1)
		if f.IsDir() {
			return os.Mkdir(dstPath, mkdirPerm)
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return err
		}

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
		return dstFile.Close()
	})
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}
