// 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.

// Package main reads a recipe spec by creating a checkout of the specified repository,
// according to the current build input. Clients should run this in the directory where
// they want the repository to be checked out. The spec is printed to stdout on success.
// On failure, a non-zero exit code is returned.
//
// This MUST be called after the input Buildbucket build has been resolved to contain a
// Gitiles commit. The build.proto object written to stdin must be base64 encoded to avoid
// logging invalid UTF-8 characters which breaks logdog.
//
// The exit codes of this program are as follows:
// 0: Ok
// 1: Unexpected fatal error
// 2: The spec file was not found
package main

import (
	"context"
	"encoding/base64"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/url"
	"os"

	"github.com/golang/protobuf/proto"

	"fuchsia.googlesource.com/infra/infra/cmd/build_init/checkout"
	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
)

const (
	// The directory containing specs in the spec repository.
	defaultSpecDir = "infra/config/generated"
	defaultGitPath = "/usr/bin/git"
)

// Exit codes
const (
	ExitOk           = 0
	ExitFatal        = 1
	ExitFileNotFound = 2
)

// Command line flags.
var (
	// The path to the spec file within the repository.
	specPath string

	// The URL of the spec repository.
	specRemote string
)

// Variables derived from user input.
var (
	// The URL to the spec repository.
	specRepoURL *url.URL

	// The build.proto object read from stdin.
	build *buildbucketpb.Build
)

func init() {
	// Required
	flag.StringVar(&specRemote, "spec_remote", "", "The URL of the spec repository")
	flag.StringVar(&specPath, "spec_path", "", "The path to the spec file relative to the repo root")
}

func main() {
	flag.Parse()
	if err := validateInputs(); err != nil {
		log.Fatal(err)
	}
	os.Exit(Execute(context.Background(), build, specRepoURL, specPath))
}

func validateInputs() (err error) {
	if specRemote == "" {
		return errors.New("missing -spec_remote")
	}

	specRepoURL, err = url.Parse(specRemote)
	if err != nil {
		return fmt.Errorf("invalid URL for -spec_remote: %v", err)
	}

	build, err = loadBuildProto(os.Stdin)
	if err != nil {
		return fmt.Errorf("failed to read build.proto: %v", err)
	}
	if err := validateBuild(*build); err != nil {
		return fmt.Errorf("invalid build message: %v", err)
	}

	if specPath == "" {
		return errors.New("must specify -spec_path")
	}

	return nil
}

func validateBuild(build buildbucketpb.Build) error {
	if build.Input == nil {
		return errors.New("build has no input")
	}
	if build.Input.GitilesCommit == nil {
		return errors.New("build input has no Gitiles commit")
	}
	if build.Builder == nil {
		return errors.New("input build has no builder information")
	}
	if build.Builder.Bucket == "" {
		return errors.New("input build's builder has no bucket")
	}
	if build.Builder.Builder == "" {
		return errors.New("input build's builder name is empty")
	}
	return nil
}

// Execute runs the program. Public for testing.
func Execute(ctx context.Context, build *buildbucketpb.Build, specRepoURL *url.URL, specPath string) (code int) {
	if err := checkout.Checkout(*build.Input, *specRepoURL); err != nil {
		log.Printf("failed to checkout %s: %v", specRepoURL.String(), err)
		return ExitFatal
	}

	if _, err := os.Stat(specPath); os.IsNotExist(err) {
		log.Printf("file not found %v", specPath)
		return ExitFileNotFound
	}
	fd, err := os.Open(specPath)
	if err != nil {
		log.Printf("failed to open file %v: %v", specPath, err)
		return ExitFatal
	}
	defer fd.Close()
	if _, err := io.Copy(os.Stdout, fd); err != nil {
		log.Printf("failed to write file to output: %v", err)
		return ExitFatal
	}

	return ExitOk
}

// Loads a buildbucketpb.Build message from the given reader. The input must be base64.
func loadBuildProto(r io.Reader) (*buildbucketpb.Build, error) {
	build := new(buildbucketpb.Build)
	decoder := base64.NewDecoder(base64.StdEncoding, r)
	bytes, err := ioutil.ReadAll(decoder)
	if err != nil {
		return nil, fmt.Errorf("failed to read build.proto: %v", err)
	}
	if err := proto.Unmarshal(bytes, build); err != nil {
		return nil, fmt.Errorf("failed to unmarshal build.proto: %v", err)
	}
	return build, nil
}
