// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/bazelbuild/bazel-gazelle/label"
)

// dependency is an external Go package/module, requested by the user of Fietsje
// directly or indirectly.
type dependency struct {
	// importpath is the Go import path that was used to import this dependency.
	importpath string
	// version at which this dependency has been requested. This can be in any form
	// that `go get` or the go module system understands.
	version string

	// locked is the 'resolved' version of a dependency, containing information about
	// the dependency's hash, etc.
	locked *locked

	// parent is the dependency that pulled in this one, or nil if pulled in by the
	// user.
	parent *dependency

	shelf *shelf

	// Build specific settings passed to gazelle.
	disableProtoBuild    bool
	forceBazelGeneration bool
	buildTags            []string
	patches              []string
	prePatches           []string
	buildExtraArgs       []string
	// replace is an importpath that this dependency will replace. If this is set, this
	// dependency will be visible in the build as 'importpath', but downloaded at
	// 'replace'/'version'. This might be slighly confusing, but follows the semantics
	// of what Gazelle exposes via 'replace' in 'go_repository'.
	replace string
}

func (d *dependency) remoteImportpath() string {
	if d.replace != "" {
		return d.replace
	}
	return d.importpath
}

// locked is information about a dependency resolved from the go module system. It
// is expensive to get, and as such it is cached both in memory (as .locked in a
// dependency) and in the shelf.
type locked struct {
	// bazelName is the external workspace name that Bazel should use for this
	// dependency, eg. com_github_google_glog.
	bazelName string
	// sum is the gomod compatible checksum of the depdendency,
	// egh1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=.
	sum string
	// semver is the gomod-compatible version of this dependency. If the dependency was
	// requested by git hash that does not resolve to a particular release, this will
	// be in the form of v0.0.0-20200520133742-deadbeefcafe.
	semver string
}

// child creates a new child dependence for this dependency, ie. one where the
// 'parent' pointer points to the dependency on which this method is called.
func (d *dependency) child(importpath, version string) *dependency {
	return &dependency{
		importpath: importpath,
		version:    version,
		shelf:      d.shelf,
		parent:     d,
	}
}

func (d *dependency) String() string {
	if d.replace != "" {
		return fmt.Sprintf("%s@%s (replacing %s)", d.replace, d.version, d.importpath)
	}
	return fmt.Sprintf("%s@%s", d.importpath, d.version)
}

// lock ensures that this dependency is locked, which means that it has been
// resolved to a particular, stable version and VCS details. We lock a dependency
// by either asking the go module subsystem (via a go module proxy or a download),
// or by consulting the shelf as a cache.
func (d *dependency) lock() error {
	// If already locked in-memory, use that.
	if d.locked != nil {
		return nil
	}

	// If already locked in the shelf, use that.
	if shelved := d.shelf.get(d.remoteImportpath(), d.version); shelved != nil {
		d.locked = shelved
		return nil
	}

	// Otherwise, download module.
	semver, _, sum, err := d.download()
	if err != nil {
		return fmt.Errorf("could not download: %v", err)
	}

	// And resolve its bazelName.
	name := label.ImportPathToBazelRepoName(d.importpath)

	d.locked = &locked{
		bazelName: name,
		sum:       sum,
		semver:    semver,
	}
	log.Printf("%s: locked to %s", d, d.locked)

	// Save locked version to shelf.
	d.shelf.put(d.remoteImportpath(), d.version, d.locked)
	return d.shelf.save()
}

func (l *locked) String() string {
	return fmt.Sprintf("%s@%s", l.bazelName, l.sum)
}

// download ensures that this dependency is download locally, and returns the
// download location and the dependency's gomod-compatible sum.
func (d *dependency) download() (version, dir, sum string, err error) {
	goroot := os.Getenv("GOROOT")
	if goroot == "" {
		err = fmt.Errorf("GOROOT must be set")
		return
	}
	goTool := filepath.Join(goroot, "bin", "go")

	query := fmt.Sprintf("%s@%s", d.remoteImportpath(), d.version)
	cmd := exec.Command(goTool, "mod", "download", "-json", "--", query)
	out, err := cmd.Output()
	if err != nil {
		log.Printf("go mod returned: %q", out)
		err = fmt.Errorf("go mod failed: %v", err)
		return
	}

	var res struct{ Version, Sum, Dir string }
	err = json.Unmarshal(out, &res)
	if err != nil {
		return
	}

	version = res.Version
	dir = res.Dir
	sum = res.Sum
	return
}
