package analyze

import (
	"bytes"
	"context"
	"fmt"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/bazelbuild/buildtools/edit"
	"github.com/bazelbuild/rules_typescript/ts_auto_deps/platform"
	"github.com/bazelbuild/rules_typescript/ts_auto_deps/workspace"
	"github.com/golang/protobuf/proto"

	appb "github.com/bazelbuild/buildtools/build_proto"
)

// pkgCacheEntry represents a set of loaded rules and a mapping from alias
// to rules from a package.
type pkgCacheEntry struct {
	// rules is all rules in a package.
	rules []*appb.Rule
	// aliases is a map from an alias label to the actual rule of the alias.
	aliases map[string]*appb.Rule
}

// QueryBasedTargetLoader uses Bazel query to load targets from BUILD files.
type QueryBasedTargetLoader struct {
	workdir     string
	bazelBinary string

	// pkgCache is a mapping from a package to all of the rules in said
	// package along with a map from aliases to actual rules.
	//
	// Keys are of the form of "<visibility>|<package>" where visibility
	// is the package that rules in package must be visible to and package
	// is the actual package that has been loaded and cached.
	//
	// Since a new target loader is constructed for each directory being
	// analyzed in the "-recursive" case, these caches will be garbage
	// collected between directories.
	pkgCache map[string]*pkgCacheEntry
	// labelCache is a mapping from a label to its loaded target.
	labelCache map[string]*appb.Target

	// queryCount is the total number of queries executed by the target loader.
	queryCount int
}

// NewQueryBasedTargetLoader constructs a new QueryBasedTargetLoader rooted
// in workdir.
func NewQueryBasedTargetLoader(workdir, bazelBinary string) *QueryBasedTargetLoader {
	return &QueryBasedTargetLoader{
		workdir:     workdir,
		bazelBinary: bazelBinary,

		pkgCache:   make(map[string]*pkgCacheEntry),
		labelCache: make(map[string]*appb.Target),
	}
}

// LoadRules uses Bazel query to load rules associated with labels from BUILD
// files.
func (q *QueryBasedTargetLoader) LoadRules(pkg string, labels []string) (map[string]*appb.Rule, error) {
	labelToTarget, err := q.LoadTargets(pkg, labels)
	if err != nil {
		return nil, err
	}

	labelToRule := make(map[string]*appb.Rule)
	for _, label := range labels {
		target := labelToTarget[label]
		if target.GetType() == appb.Target_RULE {
			labelToRule[label] = target.GetRule()
		} else {
			return nil, fmt.Errorf("target contains object of type %q instead of type %q", target.GetType(), appb.Target_RULE)
		}
	}
	return labelToRule, nil
}

// LoadTargets uses Bazel query to load targets associated with labels from BUILD
// files.
func (q *QueryBasedTargetLoader) LoadTargets(pkg string, labels []string) (map[string]*appb.Target, error) {
	var labelCacheMisses []string
	for _, label := range labels {
		if _, ok := q.labelCache[labelCacheKey(pkg, label)]; !ok {
			labelCacheMisses = append(labelCacheMisses, label)
		}
	}
	if len(labelCacheMisses) > 0 {
		var queries []string
		if pkg == "" {
			queries = labelCacheMisses
		} else {
			for _, label := range labelCacheMisses {
				queries = append(queries, fmt.Sprintf("visible(%s:*, %s)", pkg, label))
			}
		}
		r, err := q.batchQuery(queries)
		if err != nil {
			return nil, err
		}
		for _, target := range r.GetTarget() {
			label, err := q.targetLabel(target)
			if err != nil {
				return nil, err
			}
			q.labelCache[labelCacheKey(pkg, label)] = target
		}
		for _, label := range labelCacheMisses {
			key := labelCacheKey(pkg, label)
			if _, ok := q.labelCache[key]; !ok {
				// Set to nil so the result exists in the cache and is not
				// loaded again. If the nil is not added at the appropriate
				// cache key, LoadLabels will attempt to load it again when
				// next requested instead of getting a cache hit.
				q.labelCache[key] = nil
			}
		}
	}
	labelToTarget := make(map[string]*appb.Target)
	for _, label := range labels {
		labelToTarget[label] = q.labelCache[labelCacheKey(pkg, label)]
	}
	return labelToTarget, nil
}

func labelCacheKey(currentPkg, label string) string {
	return currentPkg + "^" + label
}

// possibleFilepaths generates the possible filepaths for the ts import path.
// e.g. google3/foo/bar could be foo/bar.ts or foo/bar.d.ts or foo/bar/index.ts, etc.
// Also handles special angular import paths (.ngfactory and .ngsummary).
func possibleFilepaths(importPath string) []string {
	// If the path has a suffix of ".ngfactory" or ".ngsummary", it might
	// be an Angular AOT generated file. We can infer the target as we
	// infer its corresponding ngmodule target by simply stripping the
	// ".ngfactory" / ".ngsummary" suffix
	importPath = strings.TrimSuffix(strings.TrimSuffix(importPath, ".ngsummary"), ".ngfactory")
	importPath = strings.TrimPrefix(importPath, workspace.Name()+"/")

	var possiblePaths []string

	possiblePaths = append(possiblePaths, pathWithExtensions(importPath)...)
	possiblePaths = append(possiblePaths, pathWithExtensions(filepath.Join(importPath, "index"))...)

	return possiblePaths
}

// LoadImportPaths uses Bazel Query to load targets associated with import
// paths from BUILD files.
func (q *QueryBasedTargetLoader) LoadImportPaths(ctx context.Context, currentPkg, workspaceRoot string, paths []string) (map[string]*appb.Rule, error) {
	debugf("loading imports visible to %q relative to %q: %q", currentPkg, workspaceRoot, paths)
	results := make(map[string]*appb.Rule)

	addedPaths := make(map[string]bool)
	var possibleFilePaths []string
	possiblePathToPath := make(map[string]string)
	// for all the normalized typescript import paths, generate all the possible
	// corresponding file paths
	for _, path := range paths {
		if strings.HasPrefix(path, "goog:") {
			// 'goog:' imports are resolved using an sstable.
			results[path] = nil
			continue
		}
		if strings.HasPrefix(path, "@") {
			continue
		}

		if _, ok := addedPaths[path]; !ok {
			addedPaths[path] = true

			// there isn't a one to one mapping from ts import paths to file
			// paths, so look for all the possible file paths
			pfs := possibleFilepaths(path)
			possibleFilePaths = append(possibleFilePaths, pfs...)
			for _, pf := range pfs {
				possiblePathToPath[pf] = path
			}
		}
	}

	// query for all the possible filepaths, to determine which ones are real
	r, err := q.batchQuery(possibleFilePaths)
	if err != nil {
		return nil, err
	}
	var fileLabels, packages []string
	fileToGeneratorLabel := make(map[string]string)
	pathToLabels := make(map[string][]string)
	// get the labels for all the files which exist
	for _, target := range r.GetTarget() {
		label, err := q.fileLabel(target)
		if err != nil {
			return nil, err
		}
		switch target.GetType() {
		case appb.Target_GENERATED_FILE:
			file := target.GetGeneratedFile()
			generator := file.GetGeneratingRule()
			label = file.GetName()

			fileLabels = append(fileLabels, label)
			_, pkg, _ := edit.ParseLabel(label)
			packages = append(packages, pkg)
			// a generated file can be included as a source by referencing the label
			// of the generated file, or the label of the generating rule, so check
			// for both
			fileToGeneratorLabel[labelToPath(label)] = labelToPath(generator)
			pathToLabels[possiblePathToPath[labelToPath(label)]] = append(pathToLabels[possiblePathToPath[labelToPath(label)]], label)
		case appb.Target_SOURCE_FILE:
			fileLabels = append(fileLabels, label)
			_, pkg, _ := edit.ParseLabel(label)
			packages = append(packages, pkg)
			pathToLabels[possiblePathToPath[labelToPath(label)]] = append(pathToLabels[possiblePathToPath[labelToPath(label)]], label)
		}
	}

	// load all the rules in all the packages files were found in, so we can look
	// for aliases and reexporting libraries in the same package
	pkgToAllRules, pkgToActualToAlias, err := q.loadAllRulesInPackages("", packages)
	if err != nil {
		return nil, err
	}

	for _, path := range paths {
		// look up the corresponding file label(s) for the normalized typescript
		// import path
		for _, label := range pathToLabels[path] {
			_, pkg, _ := edit.ParseLabel(label)
			// get the file path that corresponds to the normalized typescript import
			// path
			filePath := labelToPath(label)
			var matchingDeps []*appb.Rule
			allRules := pkgToAllRules[pkg]
			actualToAlias := pkgToActualToAlias[pkg]
			for _, candidate := range typeScriptRules(allRules) {
				// check if the rule has the file or the generator of the file in its
				// srcs
				possibleSources := []string{filePath}
				if gl, ok := fileToGeneratorLabel[filePath]; ok {
					possibleSources = append(possibleSources, gl)
				}
				provides, err := q.ruleProvidesImports(candidate, srcsContainsAnyFilePath(possibleSources))
				if err != nil {
					return nil, err
				}
				if !provides {
					continue
				}

				if alias, ok := actualToAlias[candidate.GetName()]; ok {
					candidate = alias
				}
				matchingDeps = append(matchingDeps, candidate)
			}
			if len(matchingDeps) > 0 {
				results[path] = chooseCanonicalRule(matchingDeps)
			}
		}
	}

	return results, nil
}

// chooseCanonicalRule chooses between rules which includes the imported file as
// a source.
func chooseCanonicalRule(rules []*appb.Rule) *appb.Rule {
	// if any of the rules is a reexporting lib assume that the reexport was
	// created for a reason
	for _, r := range rules {
		if isReexportingLib(r) {
			return r
		}
	}

	// if no rules matched the filter, just return the first rule
	return rules[0]
}

// ruleLabel returns the label for a target which is a rule.  Returns an error if
// target is not a rule.
func (q *QueryBasedTargetLoader) ruleLabel(target *appb.Target) (string, error) {
	if t := target.GetType(); t != appb.Target_RULE {
		return "", fmt.Errorf("target contains object of type %q instead of type %q", t, appb.Target_RULE)
	}
	return target.GetRule().GetName(), nil
}

// fileLabel returns the label for a target which is a file.  Returns an error if
// target is not a source file or a generated file.
func (q *QueryBasedTargetLoader) fileLabel(target *appb.Target) (string, error) {
	switch t := target.GetType(); t {
	case appb.Target_GENERATED_FILE:
		return target.GetGeneratedFile().GetName(), nil
	case appb.Target_SOURCE_FILE:
		return target.GetSourceFile().GetName(), nil
	default:
		return "", fmt.Errorf("target contains object of type %q instead of type %q or %q", t, appb.Target_SOURCE_FILE, appb.Target_GENERATED_FILE)
	}
}

// targetLabel returns the label for a target.  Returns an error if target is an
// unknown type.
func (q *QueryBasedTargetLoader) targetLabel(target *appb.Target) (string, error) {
	switch t := target.GetType(); t {
	case appb.Target_GENERATED_FILE:
		return target.GetGeneratedFile().GetName(), nil
	case appb.Target_SOURCE_FILE:
		return target.GetSourceFile().GetName(), nil
	case appb.Target_RULE:
		return target.GetRule().GetName(), nil
	case appb.Target_PACKAGE_GROUP:
		return target.GetPackageGroup().GetName(), nil
	case appb.Target_ENVIRONMENT_GROUP:
		return target.GetEnvironmentGroup().GetName(), nil
	default:
		return "", fmt.Errorf("target contains object of unknown type %q", t)
	}
}

// batchQuery runs a set of queries with a single call to Bazel query and the
// '--keep_going' flag.
func (q *QueryBasedTargetLoader) batchQuery(queries []string) (*appb.QueryResult, error) {
	// Join all of the queries with a '+' character according to Bazel's
	// syntax for running multiple queries.
	return q.query("--keep_going", strings.Join(queries, "+"))
}

func (q *QueryBasedTargetLoader) query(args ...string) (*appb.QueryResult, error) {
	n := len(args)
	if n < 1 {
		return nil, fmt.Errorf("expected at least one argument")
	}
	query := args[n-1]
	if query == "" {
		// An empty query was provided so return an empty result without
		// making a call to Bazel.
		return &appb.QueryResult{}, nil
	}
	var stdout, stderr bytes.Buffer
	args = append([]string{"query", "--output=proto"}, args...)
	q.queryCount++
	debugf("executing query #%d in %q: %s %s %q", q.queryCount, q.workdir, q.bazelBinary, strings.Join(args[:len(args)-1], " "), query)
	cmd := exec.Command(q.bazelBinary, args...)
	cmd.Dir = q.workdir
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	startTime := time.Now()
	if err := cmd.Run(); err != nil {
		// Exit status 3 is a direct result of one or more queries in a set of
		// queries not returning a result while running with the '--keep_going'
		// flag. Since one query failing to return a result does not hinder the
		// other queries from returning a result, ignore these errors.
		//
		// Herb prints "printing partial results" to indicate the same as bazel's
		// exit status 3
		if err.Error() != "exit status 3" && !strings.Contains(stderr.String(), "printing partial results") {
			// The error provided as a result is less useful than the contents of
			// stderr for debugging.
			return nil, fmt.Errorf(stderr.String())
		}
	}
	debugf("query #%d took %v", q.queryCount, time.Since(startTime))
	var result appb.QueryResult
	if err := proto.Unmarshal(stdout.Bytes(), &result); err != nil {
		return nil, err
	}
	return &result, nil
}

// ruleProvidesImports checks if the rule directly provides the import, or if
// it's a reexporting lib, if one of its deps does.
func (q *QueryBasedTargetLoader) ruleProvidesImports(rule *appb.Rule, srcMatcher func(rule *appb.Rule) bool) (bool, error) {
	if srcMatcher(rule) {
		return true, nil
	}

	if !isReexportingLib(rule) {
		return false, nil
	}

	// if the rule is a reexporting library, load all the rules that the rule
	// reexports, and check if they provide the imported paths.  This only handles
	// one level of reexport.
	_, pkg, _ := edit.ParseLabel(rule.GetName())
	// TODO(alexeagle): Batch calls to LoadLabels. Batching calls to ruleProvidesImport
	// would also be required.
	exportedRules, err := q.LoadRules(pkg, exportedLabels(rule))
	if err != nil {
		return false, err
	}
	for _, exportedRule := range exportedRules {
		if srcMatcher(exportedRule) {
			return true, nil
		}
	}

	return false, nil
}

// exportedLabels returns the labels exported by rule. Exported labels are the
// deps of a rule if the rule is an alias.
func exportedLabels(rule *appb.Rule) []string {
	var exported []string
	if isReexportingLib(rule) {
		exported = append(exported, listAttribute(rule, "deps")...)
	}
	return exported
}

// isReexportingLib checks if a library has no sources, which the TS rules use a
// way to mark a library as an alias.
func isReexportingLib(rule *appb.Rule) bool {
	return len(listAttribute(rule, "srcs")) == 0
}

// srcsContainsPath returns a function, which takes a rule, which returns true
// if the rule has a src which matches one of the possible filepaths for the
// provided typescript import path.
func srcsContainsPath(path string) func(rule *appb.Rule) bool {
	return func(rule *appb.Rule) bool {
		resolvedImportPath := resolveAgainstModuleRoot(rule, path)

		// enumerate all the possible filepaths for the resolved import path, and
		// compare against all the srcs
		possibleImportPaths := possibleFilepaths(resolvedImportPath)
		for _, src := range listAttribute(rule, "srcs") {
			for _, mi := range possibleImportPaths {
				if mi == labelToPath(src) {
					return true
				}
			}
		}

		return false
	}
}

// srcsContainsFilePath returns a function which takes a rule, which returns
// true if the rule has a src which, if pathified, equals one of the filePaths.
func srcsContainsAnyFilePath(filePaths []string) func(rule *appb.Rule) bool {
	return func(rule *appb.Rule) bool {
		for _, filePath := range filePaths {
			for _, src := range listAttribute(rule, "srcs") {
				if filePath == labelToPath(src) {
					return true
				}
			}
		}

		return false
	}
}

// loadAllRulesInPackages loads all rules in all packages.
//
// If an alias or aliases are present in the package, the rules for each alias'
// 'actual' attribute are loaded and a map from each 'actual' rule to its alias
// rule is constructed.
//
// loadAllRulesInPackages returns two maps. The first map is a map from a package
// label to all of the rules in the package. The second map is a map from a
// package to the map of 'actual' rules to alias rules for that package.
func (q *QueryBasedTargetLoader) loadAllRulesInPackages(currentPkg string, packages []string) (map[string][]*appb.Rule, map[string]map[string]*appb.Rule, error) {
	var missingPackages []string
	for _, pkg := range packages {
		if _, ok := q.pkgCache[pkgCacheKey(currentPkg, pkg)]; !ok {
			missingPackages = append(missingPackages, pkg)
		}
	}
	if len(missingPackages) > 0 {
		// Load any packages not already available in the cache.
		var queries []string
		pkgToRules := make(map[string][]*appb.Rule)
		pkgToAliasToRule := make(map[string]map[string]*appb.Rule)
		for _, pkg := range missingPackages {
			if currentPkg != "" {
				queries = append(queries, fmt.Sprintf("visible(%s:*, %s:*)", currentPkg, pkg))
			} else {
				queries = append(queries, fmt.Sprintf("%s:*", pkg))
			}
			pkgToAliasToRule[pkg] = make(map[string]*appb.Rule)
		}
		r, err := q.batchQuery(queries)
		if err != nil {
			return nil, nil, err
		}
		actualToAlias := make(map[string]*appb.Rule)
		pkgToActuals := make(map[string][]string)
		for _, target := range r.GetTarget() {
			if target.GetType() == appb.Target_RULE {
				rule := target.GetRule()
				_, pkg, _ := edit.ParseLabel(rule.GetName())
				if rule.GetRuleClass() == "alias" {
					// if the package contains an alias, derefence it (but only one layer
					// of aliases)
					actual := stringAttribute(rule, "actual")
					if actual == "" {
						return nil, nil, fmt.Errorf(`alias %q missing "actual" attribute`, rule.GetName())
					}
					actualToAlias[actual] = rule
					pkgToActuals[pkg] = append(pkgToActuals[pkg], actual)
				} else {
					pkgToRules[pkg] = append(pkgToRules[pkg], rule)
				}
			}
		}
		for pkg, actuals := range pkgToActuals {
			// Load all the aliased rules, checking if they're visible from the
			// package where they're aliased from
			resolvedActuals, err := q.LoadRules(pkg, actuals)
			if err != nil {
				return nil, nil, err
			}
			for actual, rule := range resolvedActuals {
				alias := actualToAlias[actual]
				_, pkg, _ := edit.ParseLabel(alias.GetName())
				pkgToAliasToRule[pkg][rule.GetName()] = alias
				pkgToRules[pkg] = append(pkgToRules[pkg], rule)
			}
		}
		for _, pkg := range missingPackages {
			q.pkgCache[pkgCacheKey(currentPkg, pkg)] = &pkgCacheEntry{
				rules:   pkgToRules[pkg],
				aliases: pkgToAliasToRule[pkg],
			}
		}
	}

	pkgToRules := make(map[string][]*appb.Rule)
	pkgToRuleToAlias := make(map[string]map[string]*appb.Rule)
	for _, pkg := range packages {
		cacheEntry := q.pkgCache[pkgCacheKey(currentPkg, pkg)]
		pkgToRules[pkg] = cacheEntry.rules
		pkgToRuleToAlias[pkg] = cacheEntry.aliases
	}

	return pkgToRules, pkgToRuleToAlias, nil
}

func pkgCacheKey(currentPkg, pkg string) string {
	return currentPkg + "|" + pkg
}

// dedupeLabels returns a new set of labels with no duplicates.
func dedupeLabels(labels []string) []string {
	addedLabels := make(map[string]bool)
	var uniqueLabels []string
	for _, label := range labels {
		if _, added := addedLabels[label]; !added {
			addedLabels[label] = true
			uniqueLabels = append(uniqueLabels, label)
		}
	}
	return uniqueLabels
}

// typeScriptRules returns all TypeScript rules in rules.
func typeScriptRules(rules []*appb.Rule) []*appb.Rule {
	var tsRules []*appb.Rule
	for _, rule := range rules {
		for _, supportedRuleClass := range []string{
			"ts_library",
			"ts_declaration",
			"ng_module",
		} {
			if rule.GetRuleClass() == supportedRuleClass {
				tsRules = append(tsRules, rule)
				break
			}
		}
	}
	return tsRules
}

// resolveAgainstModuleRoot resolves imported against moduleRoot and moduleName.
func resolveAgainstModuleRoot(rule *appb.Rule, imported string) string {
	moduleName := stringAttribute(rule, "module_name")
	if moduleName == "" {
		return imported
	}
	if !pathStartsWith(imported, moduleName) {
		return imported
	}
	// if module root is a file, remove the file extension, since it'll be added
	// by possibleFilepaths below
	moduleRoot := stripTSExtension(stringAttribute(rule, "module_root"))
	_, pkg, _ := edit.ParseLabel(rule.GetName())

	// resolve the import path against the module name and module root, ie if
	// the import path is @foo/bar and there's a moduleName of @foo the resolved
	// import path is location/of/foo/bar, or if there's also a moduleRoot of
	// baz, the resolved import path is location/of/foo/baz/bar
	//
	// using strings.TrimPrefix for trimming the path is ok, since
	// pathStartsWith already checked that moduleName is a proper prefix of
	// i.importPath
	return platform.Normalize(filepath.Join(pkg, moduleRoot, strings.TrimPrefix(imported, moduleName)))
}

// pathStartsWith checks if path starts with prefix, checking each path segment,
// so that @angular/core starts with @angular/core, but @angular/core-bananas
// does not
func pathStartsWith(path, prefix string) bool {
	pathParts := strings.Split(path, "/")
	prefixParts := strings.Split(prefix, "/")

	if len(prefixParts) > len(pathParts) {
		return false
	}

	for i, prefixPart := range prefixParts {
		if prefixPart != pathParts[i] {
			return false
		}
	}

	return true
}

// parsePackageName parses and returns the scope and package of imported. For
// example, "@foo/bar" would have a scope of "@foo" and a package of "bar".
func parsePackageName(imported string) (string, string) {
	firstSlash := strings.Index(imported, "/")
	if firstSlash == -1 {
		return imported, ""
	}
	afterSlash := imported[firstSlash+1:]
	if secondSlash := strings.Index(afterSlash, "/"); secondSlash > -1 {
		return imported[:firstSlash], afterSlash[:secondSlash]
	}
	return imported[:firstSlash], afterSlash
}
