// +build ignore

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func specialDir(name string) bool {
	if name == "." {
		return false
	}

	base := filepath.Base(name)
	return base[0] == '_' || base[0] == '.'
}

func emptyDir(name string) bool {
	dir, err := os.Open(name)
	defer dir.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "unable to open directory %v: %v\n", name, err)
		return true
	}

	fis, err := dir.Readdir(-1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Readdirnames(%v): %v\n", name, err)
		return true
	}

	for _, fi := range fis {
		if fi.IsDir() {
			continue
		}

		if filepath.Ext(fi.Name()) == ".go" {
			return false
		}
	}

	return true
}

func forceRelativeDirname(dirname string) string {
	if dirname == "." {
		return dirname
	}

	if strings.HasPrefix(dirname, "./") {
		return dirname
	}

	return "./" + dirname
}

func mergeCoverprofile(file *os.File, out io.Writer) error {
	_, err := file.Seek(0, 0)
	if err != nil {
		return err
	}

	rd := bufio.NewReader(file)
	_, err = rd.ReadString('\n')
	if err == io.EOF {
		return nil
	}

	if err != nil {
		return err
	}

	_, err = io.Copy(out, rd)
	if err != nil {
		return err
	}

	err = file.Close()
	if err != nil {
		return err
	}

	return err
}

func testPackage(pkg string, params []string, out io.Writer) error {
	file, err := ioutil.TempFile("", "test-coverage-")
	defer os.Remove(file.Name())
	defer file.Close()
	if err != nil {
		return err
	}

	args := []string{"test", "-cover", "-covermode", "set", "-coverprofile",
		file.Name(), pkg}
	args = append(args, params...)
	cmd := exec.Command("go", args...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout

	err = cmd.Run()
	if err != nil {
		return err
	}

	return mergeCoverprofile(file, out)
}

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "USAGE: run_tests COVERPROFILE [TESTFLAGS] [-- [PATHS]]")
		os.Exit(1)
	}

	target := os.Args[1]
	args := os.Args[2:]

	paramsForTest := []string{}
	dirs := []string{}
	for i, arg := range args {
		if arg == "--" {
			dirs = args[i+1:]
			break
		}

		paramsForTest = append(paramsForTest, arg)
	}

	if len(dirs) == 0 {
		dirs = append(dirs, ".")
	}

	file, err := os.Create(target)
	if err != nil {
		fmt.Fprintf(os.Stderr, "create coverprofile failed: %v\n", err)
		os.Exit(1)
	}

	fmt.Fprintln(file, "mode: set")

	failedTests := false
	for _, dir := range dirs {
		err := filepath.Walk(dir,
			func(p string, fi os.FileInfo, e error) error {
				if e != nil {
					return e
				}

				if !fi.IsDir() {
					return nil
				}

				if specialDir(p) {
					return filepath.SkipDir
				}

				if emptyDir(p) {
					return nil
				}

				return testPackage(forceRelativeDirname(p), paramsForTest, file)
			})

		if err != nil {
			fmt.Fprintf(os.Stderr, "walk(%q): %v\n", dir, err)
			failedTests = true
		}
	}

	err = file.Close()

	fmt.Printf("coverprofile: %v\n", file.Name())

	if failedTests {
		os.Exit(1)
	}
}
