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

// Generates a depfile for a Go package that can be consumed by Ninja.
package main

import (
	"errors"
	"flag"
	"fmt"
	"go/build"
	"log"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
)

type stringsFlag []string

func (v *stringsFlag) String() string { return strings.Join(*v, " ") }

func (v *stringsFlag) Set(s string) error {
	*v = strings.Split(s, " ")
	if *v == nil {
		*v = []string{}
	}
	return nil
}

type prefixmapFlag []struct{ from, to string }

func (v *prefixmapFlag) String() string {
	var s []string
	for _, p := range *v {
		s = append(s, fmt.Sprintf("%s=%s", p.from, p.to))
	}
	return strings.Join(s, " ")
}

func (v *prefixmapFlag) Set(s string) error {
	if strings.Count(s, "=") != 1 {
		return errors.New("argument must be of the form from=to")
	}
	i := strings.Index(s, "=")
	from, to := s[:i], s[i+1:]
	if from == "" || to == "" {
		return errors.New("from and to must be non-empty")
	}
	*v = append(*v, struct{ from, to string }{from, to})
	return nil
}

var (
	ctx       = build.Default
	output    string
	test      bool
	prefixmap = prefixmapFlag{}
)

func init() {
	flag.Var((*stringsFlag)(&ctx.BuildTags), "tags", "build tags")
	flag.StringVar(&output, "o", "", "name of the resulting executable")
	flag.BoolVar(&test, "test", false, "whether this is a test target")
	flag.Var(&prefixmap, "prefixmap", "path prefix mapping in the from=to format")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: godepfile [packages]\n")
		flag.PrintDefaults()
	}
}

func appendAndPrefix(slice []string, prefix string, src []string) []string {
	for _, s := range src {
		slice = append(slice, prefix+s)
	}
	return slice
}

func main() {
	flag.Parse()

	if len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(1)
	}

	var mu sync.Mutex
	deps := make(map[string]bool)
	paths := make(map[string]bool)

	fdlimit := make(chan struct{}, 128)
	var wg sync.WaitGroup
	var scan func(path, srcDir string, test bool)
	scan = func(path, srcDir string, test bool) {
		defer wg.Done()

		mu.Lock()
		_, done := paths[path]
		if !done {
			paths[path] = true
		}
		mu.Unlock()

		if done {
			return
		}

		if path == "C" {
			return
		}

		fdlimit <- struct{}{}
		defer func() { <-fdlimit }()

		pkg, err := ctx.Import(path, srcDir, 0)
		if err != nil {
			log.Fatalf("%s: %v", path, err)
		}

		var files []string
		srcdir := pkg.Dir + "/"
		for _, p := range prefixmap {
			if strings.HasPrefix(srcdir, p.from) {
				srcdir = p.to + srcdir[len(p.from):]
			}
		}

		files = appendAndPrefix(files, srcdir, pkg.GoFiles)
		files = appendAndPrefix(files, srcdir, pkg.CgoFiles)
		files = appendAndPrefix(files, srcdir, pkg.CFiles)
		files = appendAndPrefix(files, srcdir, pkg.CXXFiles)
		files = appendAndPrefix(files, srcdir, pkg.HFiles)
		files = appendAndPrefix(files, srcdir, pkg.SFiles)
		files = appendAndPrefix(files, srcdir, pkg.SwigFiles)
		files = appendAndPrefix(files, srcdir, pkg.SwigCXXFiles)

		if test {
			files = appendAndPrefix(files, srcdir, pkg.TestGoFiles)
			files = appendAndPrefix(files, srcdir, pkg.XTestGoFiles)
		}

		mu.Lock()
		for _, file := range files {
			deps[file] = true
		}
		mu.Unlock()

		if pkg.Name == "main" && output == "" {
			bindir := os.Getenv("GOBIN")
			if bindir == "" {
				bindir = pkg.BinDir
			}
			if ctx.GOOS == runtime.GOOS && ctx.GOARCH == runtime.GOARCH {
				output = ctx.JoinPath(bindir, path)
			} else {
				output = ctx.JoinPath(bindir, ctx.GOOS+"_"+ctx.GOARCH, path)
			}
		}

		for _, imp := range pkg.Imports {
			wg.Add(1)
			go scan(imp, pkg.Dir, false)
		}

		if test {
			for _, imp := range pkg.TestImports {
				wg.Add(1)
				go scan(imp, pkg.Dir, false)
			}
			for _, imp := range pkg.XTestImports {
				wg.Add(1)
				go scan(imp, pkg.Dir, false)
			}
		}
	}

	for _, root := range flag.Args() {
		wg.Add(1)
		go scan(root, "", test)
	}
	wg.Wait()

	fmt.Printf("%s:", output)
	var depnames []string
	for path := range deps {
		depnames = append(depnames, path)
	}
	sort.Strings(depnames)
	for path := range deps {
		fmt.Printf(" %s", path)
	}
	fmt.Printf("\n")
}
