// Copyright 2014 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 (
	"errors"
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/tools/go/types"
)

var (
	source  = flag.String("s", "", "only consider packages from src, where src is one of the supported compilers")
	verbose = flag.Bool("v", false, "verbose mode")
)

// lists of registered sources and corresponding importers
var (
	sources      []string
	importers    []types.Importer
	importFailed = errors.New("import failed")
)

// map of imported packages
var packages = make(map[string]*types.Package)

func usage() {
	fmt.Fprintln(os.Stderr, "usage: godex [flags] {path|qualifiedIdent}")
	flag.PrintDefaults()
	os.Exit(2)
}

func report(msg string) {
	fmt.Fprintln(os.Stderr, "error: "+msg)
	os.Exit(2)
}

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

	if flag.NArg() == 0 {
		report("no package name, path, or file provided")
	}

	imp := tryImports
	if *source != "" {
		imp = lookup(*source)
		if imp == nil {
			report("source (-s argument) must be one of: " + strings.Join(sources, ", "))
		}
	}

	for _, arg := range flag.Args() {
		path, name := splitPathIdent(arg)
		logf("\tprocessing %q: path = %q, name = %s\n", arg, path, name)

		// generate possible package path prefixes
		// (at the moment we do this for each argument - should probably cache the generated prefixes)
		prefixes := make(chan string)
		go genPrefixes(prefixes, !filepath.IsAbs(path) && !build.IsLocalImport(path))

		// import package
		pkg, err := tryPrefixes(packages, prefixes, path, imp)
		if err != nil {
			logf("\t=> ignoring %q: %s\n", path, err)
			continue
		}

		// filter objects if needed
		var filter func(types.Object) bool
		if name != "" {
			filter = func(obj types.Object) bool {
				// TODO(gri) perhaps use regular expression matching here?
				return obj.Name() == name
			}
		}

		// print contents
		print(os.Stdout, pkg, filter)
	}
}

func logf(format string, args ...interface{}) {
	if *verbose {
		fmt.Fprintf(os.Stderr, format, args...)
	}
}

// splitPathIdent splits a path.name argument into its components.
// All but the last path element may contain dots.
func splitPathIdent(arg string) (path, name string) {
	if i := strings.LastIndex(arg, "."); i >= 0 {
		if j := strings.LastIndex(arg, "/"); j < i {
			// '.' is not part of path
			path = arg[:i]
			name = arg[i+1:]
			return
		}
	}
	path = arg
	return
}

// tryPrefixes tries to import the package given by (the possibly partial) path using the given importer imp
// by prepending all possible prefixes to path. It returns with the first package that it could import, or
// with an error.
func tryPrefixes(packages map[string]*types.Package, prefixes chan string, path string, imp types.Importer) (pkg *types.Package, err error) {
	for prefix := range prefixes {
		actual := path
		if prefix == "" {
			// don't use filepath.Join as it will sanitize the path and remove
			// a leading dot and then the path is not recognized as a relative
			// package path by the importers anymore
			logf("\ttrying no prefix\n")
		} else {
			actual = filepath.Join(prefix, path)
			logf("\ttrying prefix %q\n", prefix)
		}
		pkg, err = imp(packages, actual)
		if err == nil {
			break
		}
		logf("\t=> importing %q failed: %s\n", actual, err)
	}
	return
}

// tryImports is an importer that tries all registered importers
// successively until one of them succeeds or all of them failed.
func tryImports(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
	for i, imp := range importers {
		logf("\t\ttrying %s import\n", sources[i])
		pkg, err = imp(packages, path)
		if err == nil {
			break
		}
		logf("\t\t=> %s import failed: %s\n", sources[i], err)
	}
	return
}

// protect protects an importer imp from panics and returns the protected importer.
func protect(imp types.Importer) types.Importer {
	return func(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
		defer func() {
			if recover() != nil {
				pkg = nil
				err = importFailed
			}
		}()
		return imp(packages, path)
	}
}

// register registers an importer imp for a given source src.
func register(src string, imp types.Importer) {
	if lookup(src) != nil {
		panic(src + " importer already registered")
	}
	sources = append(sources, src)
	importers = append(importers, protect(imp))
}

// lookup returns the importer imp for a given source src.
func lookup(src string) types.Importer {
	for i, s := range sources {
		if s == src {
			return importers[i]
		}
	}
	return nil
}

func genPrefixes(out chan string, all bool) {
	out <- ""
	if all {
		platform := build.Default.GOOS + "_" + build.Default.GOARCH
		dirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)
		for _, dirname := range dirnames {
			walkDir(filepath.Join(dirname, "pkg", platform), "", out)
		}
	}
	close(out)
}

func walkDir(dirname, prefix string, out chan string) {
	fiList, err := ioutil.ReadDir(dirname)
	if err != nil {
		return
	}
	for _, fi := range fiList {
		if fi.IsDir() && !strings.HasPrefix(fi.Name(), ".") {
			prefix := filepath.Join(prefix, fi.Name())
			out <- prefix
			walkDir(filepath.Join(dirname, fi.Name()), prefix, out)
		}
	}
}
