// Copyright 2020 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 (
	"flag"
	"fmt"
	"go/go2go"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

var gotool = filepath.Join(runtime.GOROOT(), "bin", "go")

var cmds = map[string]bool{
	"build":     true,
	"run":       true,
	"test":      true,
	"translate": true,
}

// tagsFlag is the implementation of the -tags flag.
type tagsFlag []string

var buildTags tagsFlag

func (v *tagsFlag) Set(s string) error {
	// Split on commas, ignore empty strings.
	*v = []string{}
	for _, s := range strings.Split(s, ",") {
		if s != "" {
			*v = append(*v, s)
		}
	}
	return nil
}

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

func main() {
	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		usage()
	}

	if !cmds[args[0]] {
		usage()
	}
	cmd := args[0]

	fs := flag.NewFlagSet("", flag.ContinueOnError)
	fs.Var((*tagsFlag)(&buildTags), "tags", "tag,list")
	fs.Parse(args[1:])

	args = fs.Args()

	importerTmpdir, err := ioutil.TempDir("", "go2go")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(importerTmpdir)

	importer := go2go.NewImporter(importerTmpdir)

	if len(buildTags) > 0 {
		importer.SetTags(buildTags)
	}

	var rundir string
	if cmd == "run" {
		tmpdir := copyToTmpdir(args)
		defer os.RemoveAll(tmpdir)
		translate(importer, tmpdir)
		var nargs []string
		for _, arg := range args {
			base := filepath.Base(arg)
			f := strings.TrimSuffix(base, ".go2") + ".go"
			nargs = append(nargs, f)
		}
		args = nargs
		rundir = tmpdir
	} else if cmd == "translate" && isGo2Files(args...) {
		for _, arg := range args {
			translateFile(importer, arg)
		}
	} else {
		for _, dir := range expandPackages(args) {
			translate(importer, dir)
		}
	}

	if cmd != "translate" {
		if len(buildTags) > 0 {
			args = append([]string{
				fmt.Sprintf("-tags=%s", strings.Join(buildTags, ",")),
			}, args...)
		}

		args = append([]string{cmd}, args...)

		cmd := exec.Command(gotool, args...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Dir = rundir
		gopath := importerTmpdir
		if go2path := os.Getenv("GO2PATH"); go2path != "" {
			gopath += string(os.PathListSeparator) + go2path
		}
		if oldGopath := os.Getenv("GOPATH"); oldGopath != "" {
			gopath += string(os.PathListSeparator) + oldGopath
		}
		cmd.Env = append(os.Environ(),
			"GOPATH="+gopath,
			"GO111MODULE=off",
		)
		if err := cmd.Run(); err != nil {
			die(fmt.Sprintf("%s %v failed: %v", gotool, args, err))
		}
	}
}

// isGo2Files reports whether the arguments are a list of .go2 files.
func isGo2Files(args ...string) bool {
	for _, arg := range args {
		if filepath.Ext(arg) != ".go2" {
			return false
		}
	}
	return true
}

// expandPackages returns a list of directories expanded from packages.
func expandPackages(pkgs []string) []string {
	if len(pkgs) == 0 {
		return []string{"."}
	}
	go2path := os.Getenv("GO2PATH")
	var dirs []string
pkgloop:
	for _, pkg := range pkgs {
		if go2path != "" {
			for _, pd := range strings.Split(go2path, string(os.PathListSeparator)) {
				d := filepath.Join(pd, "src", pkg)
				if fi, err := os.Stat(d); err == nil && fi.IsDir() {
					dirs = append(dirs, d)
					continue pkgloop
				}
			}
		}

		cmd := exec.Command(gotool, "list", "-f", "{{.Dir}}", pkg)
		cmd.Stderr = os.Stderr
		if go2path != "" {
			gopath := go2path
			if oldGopath := os.Getenv("GOPATH"); oldGopath != "" {
				gopath += string(os.PathListSeparator) + oldGopath
			}
			cmd.Env = append(os.Environ(),
				"GOPATH="+gopath,
				"GO111MODULE=off",
			)
		}
		out, err := cmd.Output()
		if err != nil {
			die(fmt.Sprintf("%s list %q failed: %v", gotool, pkg, err))
		}
		dirs = append(dirs, strings.Split(string(out), "\n")...)
	}
	return dirs
}

// copyToTmpdir copies files into a temporary directory.
func copyToTmpdir(files []string) string {
	if len(files) == 0 {
		die("no files to run")
	}
	tmpdir, err := ioutil.TempDir("", "go2go-run")
	if err != nil {
		die(err.Error())
	}
	for _, file := range files {
		data, err := ioutil.ReadFile(file)
		if err != nil {
			die(err.Error())
		}
		if err := ioutil.WriteFile(filepath.Join(tmpdir, filepath.Base(file)), data, 0444); err != nil {
			die(err.Error())
		}
	}
	return tmpdir
}

// usage reports a usage message and exits with failure.
func usage() {
	fmt.Fprint(os.Stderr, `Usage: go2go <command> [arguments]

The commands are:

	build      translate and build packages
	run        translate and run list of files
	test       translate and test packages
	translate  translate .go2 files into .go files
`)
	os.Exit(2)
}

// die reports an error and exits.
func die(msg string) {
	fmt.Fprintln(os.Stderr, msg)
	os.Exit(1)
}
