// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package discovery

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

// FindPlugins looks in the given directories for files whose filenames
// suggest that they are plugins of the given kind (e.g. "provider") and
// returns a PluginMetaSet representing the discovered potential-plugins.
//
// Currently this supports two different naming schemes. The current
// standard naming scheme is a subdirectory called $GOOS-$GOARCH containing
// files named terraform-$KIND-$NAME-V$VERSION. The legacy naming scheme is
// files directly in the given directory whose names are like
// terraform-$KIND-$NAME.
//
// Only one plugin will be returned for each unique plugin (name, version)
// pair, with preference given to files found in earlier directories.
//
// This is a convenience wrapper around FindPluginPaths and ResolvePluginsPaths.
func FindPlugins(kind string, dirs []string) PluginMetaSet {
	return ResolvePluginPaths(FindPluginPaths(kind, dirs))
}

// FindPluginPaths looks in the given directories for files whose filenames
// suggest that they are plugins of the given kind (e.g. "provider").
//
// The return value is a list of absolute paths that appear to refer to
// plugins in the given directories, based only on what can be inferred
// from the naming scheme. The paths returned are ordered such that files
// in later dirs appear after files in earlier dirs in the given directory
// list. Within the same directory plugins are returned in a consistent but
// undefined order.
func FindPluginPaths(kind string, dirs []string) []string {
	// This is just a thin wrapper around findPluginPaths so that we can
	// use the latter in tests with a fake machineName so we can use our
	// test fixtures.
	return findPluginPaths(kind, dirs)
}

func findPluginPaths(kind string, dirs []string) []string {
	prefix := "terraform-" + kind + "-"

	ret := make([]string, 0, len(dirs))

	for _, dir := range dirs {
		items, err := ioutil.ReadDir(dir)
		if err != nil {
			// Ignore missing dirs, non-dirs, etc
			continue
		}

		log.Printf("[DEBUG] checking for %s in %q", kind, dir)

		for _, item := range items {
			fullName := item.Name()

			if !strings.HasPrefix(fullName, prefix) {
				continue
			}

			// New-style paths must have a version segment in filename
			if strings.Contains(strings.ToLower(fullName), "_v") {
				absPath, err := filepath.Abs(filepath.Join(dir, fullName))
				if err != nil {
					log.Printf("[ERROR] plugin filepath error: %s", err)
					continue
				}

				// Check that the file we found is usable
				if !pathIsFile(absPath) {
					log.Printf("[ERROR] ignoring non-file %s", absPath)
					continue
				}

				log.Printf("[DEBUG] found %s %q", kind, fullName)
				ret = append(ret, filepath.Clean(absPath))
				continue
			}

			// Legacy style with files directly in the base directory
			absPath, err := filepath.Abs(filepath.Join(dir, fullName))
			if err != nil {
				log.Printf("[ERROR] plugin filepath error: %s", err)
				continue
			}

			// Check that the file we found is usable
			if !pathIsFile(absPath) {
				log.Printf("[ERROR] ignoring non-file %s", absPath)
				continue
			}

			log.Printf("[WARN] found legacy %s %q", kind, fullName)

			ret = append(ret, filepath.Clean(absPath))
		}
	}

	return ret
}

// Returns true if and only if the given path refers to a file or a symlink
// to a file.
func pathIsFile(path string) bool {
	info, err := os.Stat(path)
	if err != nil {
		return false
	}

	return !info.IsDir()
}

// ResolvePluginPaths takes a list of paths to plugin executables (as returned
// by e.g. FindPluginPaths) and produces a PluginMetaSet describing the
// referenced plugins.
//
// If the same combination of plugin name and version appears multiple times,
// the earlier reference will be preferred. Several different versions of
// the same plugin name may be returned, in which case the methods of
// PluginMetaSet can be used to filter down.
func ResolvePluginPaths(paths []string) PluginMetaSet {
	s := make(PluginMetaSet)

	type nameVersion struct {
		Name    string
		Version string
	}
	found := make(map[nameVersion]struct{})

	for _, path := range paths {
		baseName := strings.ToLower(filepath.Base(path))
		if !strings.HasPrefix(baseName, "terraform-") {
			// Should never happen with reasonable input
			continue
		}

		baseName = baseName[10:]
		firstDash := strings.Index(baseName, "-")
		if firstDash == -1 {
			// Should never happen with reasonable input
			continue
		}

		baseName = baseName[firstDash+1:]
		if baseName == "" {
			// Should never happen with reasonable input
			continue
		}

		// Trim the .exe suffix used on Windows before we start wrangling
		// the remainder of the path.
		baseName = strings.TrimSuffix(baseName, ".exe")

		parts := strings.SplitN(baseName, "_v", 2)
		name := parts[0]
		version := VersionZero
		if len(parts) == 2 {
			version = parts[1]
		}

		// Auto-installed plugins contain an extra name portion representing
		// the expected plugin version, which we must trim off.
		if underX := strings.Index(version, "_x"); underX != -1 {
			version = version[:underX]
		}

		if _, ok := found[nameVersion{name, version}]; ok {
			// Skip duplicate versions of the same plugin
			// (We do this during this step because after this we will be
			// dealing with sets and thus lose our ordering with which to
			// decide preference.)
			continue
		}

		s.Add(PluginMeta{
			Name:    name,
			Version: VersionStr(version),
			Path:    path,
		})
		found[nameVersion{name, version}] = struct{}{}
	}

	return s
}
