// Copyright 2021 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package protoc

import (
	"context"
	"encoding/json"
	"go/build"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"go.chromium.org/luci/common/data/stringset"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
)

// StagedInputs represents a staging directory with Go modules symlinked into
// a way that `protoc` sees a consistent --proto_path.
type StagedInputs struct {
	Paths        []string // absolute paths to search for protos
	InputDir     string   // absolute path to the directory with protos to compile
	OutputDir    string   // a directory with Go package root to put *.pb.go under
	ProtoFiles   []string // names of proto files in InputDir
	ProtoPackage string   // proto package path matching InputDir
	tmp          string   // if not empty, should be deleted (recursively) when done
}

// Cleanup removes the temporary staging directory.
func (s *StagedInputs) Cleanup() error {
	if s.tmp != "" {
		return os.RemoveAll(s.tmp)
	}
	return nil
}

// StageGoInputs stages a directory with Go Modules symlinked in appropriate
// places and prepares corresponding --proto_path paths.
//
// If `inputDir` or any of given `protoImportPaths` are under any of the
// directories being staged, changes their paths to be rooted in the staged
// directory root. Such paths still point to the exact same directories, just
// through symlinks in the staging area.
func StageGoInputs(ctx context.Context, inputDir string, mods, rootMods, protoImportPaths []string) (inputs *StagedInputs, err error) {
	// Try to find the main module (if running in modules mode). We'll put
	// generated files there.
	var mainMod *moduleInfo
	if os.Getenv("GO111MODULE") != "off" {
		var err error
		if mainMod, err = getModuleInfo("main"); err != nil {
			return nil, errors.Annotate(err, "could not find the main module").Err()
		}
		logging.Debugf(ctx, "The main module is %q at %q", mainMod.Path, mainMod.Dir)
	} else {
		logging.Debugf(ctx, "Running in GOPATH mode")
	}

	// If running in Go Modules mode, always put the main module and luci-go
	// modules into the proto path.
	modules := stringset.NewFromSlice(mods...)
	modules.AddAll(rootMods)
	if mainMod != nil {
		modules.Add(mainMod.Path)
		if luciInfo, err := getModuleInfo("go.chromium.org/luci"); err == nil {
			modules.Add(luciInfo.Path)
		} else {
			logging.Warningf(ctx, "LUCI protos will be unavailable: %s", err)
		}
	}

	// The directory with staged modules to use as --proto_path.
	stagedRoot, err := ioutil.TempDir("", "cproto")
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			os.RemoveAll(stagedRoot)
		}
	}()

	// Stage requested modules into a temp directory using symlinks.
	mapping, err := stageModules(stagedRoot, modules.ToSortedSlice())
	if err != nil {
		return nil, err
	}

	// "Relocate" paths into the staging directory. It doesn't change what they
	// point to, just makes them resolve through symlinks in the staging
	// directory, if possible. Also convert path to absolute and verify they are
	// existing directories. This is needed to make relative paths calculation in
	// protoc happy.
	relocatePath := func(p string) (string, error) {
		abs, err := filepath.Abs(p)
		if err != nil {
			return "", err
		}
		switch s, err := os.Stat(abs); {
		case err != nil:
			return "", err
		case !s.IsDir():
			return "", errors.Reason("%q is not a directory", p).Err()
		}
		for pre, post := range mapping {
			if abs == pre {
				return post, nil
			}
			if strings.HasPrefix(abs, pre+string(filepath.Separator)) {
				return post + abs[len(pre):], nil
			}
		}
		return abs, nil
	}

	inputDir, err = relocatePath(inputDir)
	if err != nil {
		return nil, errors.Annotate(err, "bad input directory").Err()
	}

	// Prep import paths: union of GOPATH (if any), staged modules and
	// relocated `protoImportPaths`.
	var paths []string
	paths = append(paths, stagedRoot)
	for _, mod := range rootMods {
		paths = append(paths, filepath.Join(stagedRoot, mod))
	}
	paths = append(paths, build.Default.SrcDirs()...)

	// Explicitly requested import paths come last. This is needed to make sure
	// protoc is not confused if an input *.proto name shows up in one of the
	// protoImportPaths. It already shows up in the stagedRoot proto path (by
	// construction). If protoc sees the input proto in another --proto_path
	// that comes *before* stagedRoot, it spits out this confusing error:
	//
	//   Input is shadowed in the --proto_path by "<explicitly requested path>".
	//   Either use the latter file as your input or reorder the --proto_path so
	//   that the former file's location comes first.
	//
	// By putting protoImportPaths last, we "reorder the --proto_path so that the
	// former file's location comes first".
	for _, p := range protoImportPaths {
		p, err := relocatePath(p)
		if err != nil {
			return nil, errors.Annotate(err, "bad proto import path").Err()
		}
		paths = append(paths, p)
	}

	// Include googleapis proto files vendored into the luci-go repo.
	for _, p := range paths {
		abs := filepath.Join(p, "go.chromium.org", "luci", "common", "proto", "googleapis")
		if _, err := os.Stat(abs); err == nil {
			paths = append(paths, abs)
			break
		}
	}

	// In Go Modules mode, put outputs into a staging directory. They'll end up in
	// the correct module based on go_package definitions. In GOPATH mode, put
	// them into the GOPATH entry that contains the input directory.
	var outputDir string
	if mainMod != nil {
		outputDir = stagedRoot
	} else {
		srcDirs := build.Default.SrcDirs()
		for _, p := range srcDirs {
			if strings.HasPrefix(inputDir, p) {
				outputDir = p
				break
			}
		}
		if outputDir == "" {
			return nil, errors.Annotate(err, "the input directory %q is not under GOPATH %v", inputDir, srcDirs).Err()
		}
	}

	// Find .proto files in the staged input directory.
	protoFiles, err := findProtoFiles(inputDir)
	if err != nil {
		return nil, err
	}
	if len(protoFiles) == 0 {
		return nil, errors.Reason("%s: no .proto files found", inputDir).Err()
	}

	// Discover the proto package path by locating `inputDir` among import paths.
	var protoPkg string
	for _, p := range paths {
		if strings.HasPrefix(inputDir, p) {
			protoPkg = filepath.ToSlash(inputDir[len(p)+1:])
			break
		}
	}
	if protoPkg == "" {
		return nil, errors.Reason("the input directory %q is outside of any proto path %v", inputDir, paths).Err()
	}

	return &StagedInputs{
		Paths:        paths,
		InputDir:     inputDir,
		OutputDir:    outputDir,
		ProtoFiles:   protoFiles,
		ProtoPackage: protoPkg,
		tmp:          stagedRoot,
	}, nil
}

// StageGenericInputs just prepares StagedInputs from some generic directories
// on disk.
//
// Unlike StageGoInputs it doesn't try to derive any information from what's
// there. Just converts paths to absolute and discovers *.proto files.
func StageGenericInputs(ctx context.Context, inputDir string, protoImportPaths []string) (*StagedInputs, error) {
	absInputDir, err := filepath.Abs(inputDir)
	if err != nil {
		return nil, errors.Annotate(err, "could not make path %q absolute", inputDir).Err()
	}

	absImportPaths := make([]string, 0, len(protoImportPaths)+1)
	includesInputDir := false
	protoPackageDir := ""
	for _, path := range protoImportPaths {
		abs, err := filepath.Abs(path)
		if err != nil {
			return nil, errors.Annotate(err, "could not make path %q absolute", path).Err()
		}
		absImportPaths = append(absImportPaths, abs)
		if strings.HasPrefix(absInputDir, abs+string(filepath.Separator)) && !includesInputDir {
			includesInputDir = true
			protoPackageDir = filepath.ToSlash(absInputDir[len(abs)+1:])
		}
	}

	// Add the input directory to the proto import path only if it is not already
	// included via some existing import path. Adding it twice confuses protoc.
	// Not adding it at all breaks relative imports.
	if !includesInputDir {
		absImportPaths = append(absImportPaths, absInputDir)
		protoPackageDir = "."
	}

	protoFiles, err := findProtoFiles(absInputDir)
	if err != nil {
		return nil, err
	}
	if len(protoFiles) == 0 {
		return nil, errors.Reason(".proto files not found").Err()
	}

	return &StagedInputs{
		Paths:        absImportPaths,
		InputDir:     absInputDir,
		OutputDir:    absInputDir, // drop generated files (if any) right there
		ProtoFiles:   protoFiles,
		ProtoPackage: protoPackageDir,
	}, nil
}

// stageModules symlinks given Go modules (and only them) at their module paths.
//
// Returns a map "original abs path => symlinked abs path".
func stageModules(root string, mods []string) (map[string]string, error) {
	mapping := make(map[string]string, len(mods))
	for _, m := range mods {
		info, err := getModuleInfo(m)
		if err != nil {
			return nil, err
		}
		dest := filepath.Join(root, filepath.FromSlash(m))
		if err := os.MkdirAll(filepath.Dir(dest), 0700); err != nil {
			return nil, err
		}
		if err := os.Symlink(info.Dir, dest); err != nil {
			return nil, err
		}
		mapping[info.Dir] = dest
	}
	return mapping, nil
}

type moduleInfo struct {
	Path string // e.g. "go.chromium.org/luci"
	Dir  string // e.g. "/home/work/gomodcache/.../luci"
}

// getModuleInfo returns the information about a module.
//
// Pass "main" to get the information about the main module.
func getModuleInfo(mod string) (*moduleInfo, error) {
	args := []string{"-mod=readonly", "-m"}
	if mod != "main" {
		args = append(args, mod)
	}
	info := &moduleInfo{}
	if err := goList(args, info); err != nil {
		return nil, errors.Annotate(err, "failed to resolve path of module %q", mod).Err()
	}
	return info, nil
}

// goList calls "go list -json <args>" and parses the result.
func goList(args []string, out any) error {
	cmd := exec.Command("go", append([]string{"list", "-json"}, args...)...)
	buf, err := cmd.Output()
	if err != nil {
		if er, ok := err.(*exec.ExitError); ok && len(er.Stderr) > 0 {
			return errors.Reason("%s", er.Stderr).Err()
		}
		return err
	}
	return json.Unmarshal(buf, out)
}

// findProtoFiles returns .proto files in dir. The returned file paths
// are relative to dir.
func findProtoFiles(dir string) ([]string, error) {
	files, err := filepath.Glob(filepath.Join(dir, "*.proto"))
	if err != nil {
		return nil, err
	}
	for i, f := range files {
		files[i] = filepath.Base(f)
	}
	return files, err
}
