// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Binary main converts Jiri source manifests (JSON) into Repo manifests (XML).
//
// This tool is specific to Fuchsia in that it only understands the subset of either
// manifest schema sufficient for producing Repo manifests that can be used with go/ab.
//
// The key elements of the Repo manifest are:
// * <remote>
// * <default>
// * <project>
//
// <default> is mostly filled from user-input and specifies the default GoB remote and
// branch for <project> elements in the manifest.
//
// <remote> and <project> elements are built from the entries of the "directories"
// property from the input source manifest.
//
// Source manifests are created relative to some working directory, so there is usually
// (always?) a directory entry named ".". This is represented in the Repo manifest by a
// <project> whose name attribute is the basename of the directory>git_checkout>repo_url.
//
// For documentation on Repo manifests, see go/repo-manifests-explained and go/repo.
//
// For documentation on Jiri manifest, see this proto:
// https://chromium.googlesource.com/external/github.com/luci/recipes-py/+/refs/heads/master/recipe_engine/source_manifest.proto
package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"go.fuchsia.dev/infra/cmd/jiri2repo/jiri"
	"go.fuchsia.dev/infra/cmd/jiri2repo/repo"
)

var bin = filepath.Base(os.Args[0])

// Command-line flags.
var (
	// The release branch name.
	//
	// This is used as the <default> revision in the repo manifest.
	branch string

	// The GoB host that will house the output Repo manifest.
	//
	// This is set as the <default> remote in the repo manifest.
	defaultRemote string

	// Where to write output. Defaults to stdout.
	output string
)

const gobHostSuffix = ".googlesource.com"

var usageTemplate = template.Must(template.New("usage").Parse(`
{{.Cmd}} [options] SOURCE_MANIFEST_PATH

Converts a Jiri source manifest to a Repo manifest.

EXAMPLES:

{{.Cmd}} -branch releases/canary -remote fuchsia ./source_manifest.json
{{.Cmd}} -remote fuchsia ./source_manifest.json
{{.Cmd}} -remote fuchsia -output default.xml ./source_manifest.json

OPTIONS:
`))

func usage() {
	usageArgs := struct{ Cmd string }{Cmd: bin}
	usageTemplate.Execute(flag.CommandLine.Output(), usageArgs)
	flag.PrintDefaults()
	os.Exit(1)
}

func init() {
	flag.Usage = usage
	flag.StringVar(&branch, "branch", "refs/heads/master", "The release branch")
	flag.StringVar(&output, "output", "", "Optional filepath to write output to. If empty, stdout is used")
	flag.StringVar(&defaultRemote, "remote", "", "The SSO GoB host that will house the output Repo manifest")
}

func main() {
	flag.Parse()
	if err := validateArgs(); err != nil {
		log.Print(err)
		flag.Usage()
	}

	if err := execute(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func validateArgs() error {
	if flag.NArg() != 1 {
		return errors.New("expected one positional argument")
	}
	if branch == "" {
		return errors.New("missing -branch")
	}
	if defaultRemote == "" {
		return errors.New("missing -remote")
	}
	return nil
}

func execute(ctx context.Context) (err error) {
	var in jiri.SourceManifest
	var out repo.Manifest

	sourceManifestPath := flag.Arg(0)
	if err := jiri.ReadSourceManifestFile(sourceManifestPath, &in); err != nil {
		return fmt.Errorf("failed to read %s: %v", sourceManifestPath, err)
	}

	defaults := repo.Default{
		Branch: branch,
		Remote: defaultRemote,
	}

	if err := convert(in, &out, defaults); err != nil {
		return fmt.Errorf("conversion failed: %v", err)
	}

	var w io.Writer = os.Stdout
	if output != "" {
		w, err = os.Create(output)
		if err != nil {
			return fmt.Errorf("failed to open output file %q: %v", output, err)
		}
	}
	if err := repo.WriteManifest(w, &out); err != nil {
		return fmt.Errorf("failed to write Repo manifest: %v", err)
	}

	return nil
}

// Converts the input source manifest to a Repo manifest. Writes the output to out.
//
// defaults is written as the Repo manifest's <default> element. Any ".googlesource.com"
// suffix is stripped from defaults.Remote before writing the output.
func convert(in jiri.SourceManifest, out *repo.Manifest, defaults repo.Default) error {
	// Tracks GoB remote names to avoid outputting duplicate <remote> elements.
	remotes := make(map[string]bool)

	// Remotes are recorded without GoB host suffixes in Repo manifests.
	defaults.Remote = strings.TrimSuffix(defaults.Remote, gobHostSuffix)

	// Convert each source manifest directory to a <project> and <remote>
	for name, dir := range in.Directories {
		project, remote, err := convertDirectory(name, *dir, defaults)
		if err != nil {
			return err
		}
		out.Project = append(out.Project, *project)
		if _, ok := remotes[remote.Name]; !ok {
			remotes[remote.Name] = true
			out.Remote = append(out.Remote, *remote)
		}
	}

	// If there is no <remote> with the specified GoB remote name, either the user
	// mistakenly entered the wrong default remote or the output Repo manifest will be
	// stored on a git host that is separate from any of the repos listed in the manifest.
	// The second scenario is unlikely; Err on the side of caution and fail.
	if !remotes[defaults.Remote] {
		return fmt.Errorf("the input manifest contained no projects from the specified default remote %q", defaults.Remote)
	}

	out.Default = defaults
	out.Comment = fmt.Sprintf("Auto generated by %s. DO NOT EDIT", bin)

	// Sort sections for deterministic output.
	sort.Slice(out.Remote, func(a, b int) bool {
		return out.Remote[a].Name < out.Remote[b].Name
	})
	sort.Slice(out.Project, func(a, b int) bool {
		return out.Project[a].Name < out.Project[b].Name
	})

	return nil
}

// convertDirectory converts a Jiri source manifest directory object into a set of Repo
// <project> and <remote> elements.
//
// The directory name is used as the project's name and path. If the directory name is ".",
// the basename of directory's repository url is used instead. The empty string is not
// allowed and results in an error.
func convertDirectory(name string, d jiri.SourceManifest_Directory, defaults repo.Default) (*repo.Project, *repo.Remote, error) {
	// Resolve the directory name.
	if name == "." {
		name = filepath.Base(d.GitCheckout.RepoUrl)
	}
	if name == "" {
		return nil, nil, fmt.Errorf("source manifest directory has no name: %v", d)
	}

	checkout := d.GitCheckout
	reviewURL, err := ssoCodeReviewURL(checkout.RepoUrl)
	if err != nil {
		return nil, nil, err
	}

	remote := &repo.Remote{
		// By convention the remote name is the GoB hostname and not the review hostname.
		Name:   strings.TrimSuffix(reviewURL.Host, "-review"),
		Fetch:  checkout.FetchRef,
		Review: reviewURL.String(),
	}
	project := &repo.Project{
		Name:     name,
		Path:     name,
		Remote:   remote.Name,
		Revision: checkout.Revision,
	}

	if project.Remote == defaults.Remote {
		project.Remote = ""
	}
	return project, remote, nil
}

func ssoCodeReviewURL(gobURL string) (*url.URL, error) {
	u, err := url.Parse(gobURL)
	if err != nil {
		return nil, err
	}
	// URL.Hostname() returns the empty string if the scheme is empty.
	if u.Scheme == "" {
		return nil, fmt.Errorf("invalid URL %q: origin has no scheme", gobURL)
	}
	hostname := u.Hostname()
	if !strings.HasSuffix(hostname, gobHostSuffix) {
		return nil, fmt.Errorf("cannot compute code review host for non Git-on-Borg hostname %q", hostname)
	}
	host := strings.TrimSuffix(hostname, gobHostSuffix)

	return &url.URL{
		Scheme: "sso",
		Host:   host + "-review",
		Path:   "/",
	}, nil
}
