// Copyright 2015 The Go 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

import (
	"archive/tar"
	"bytes"
	"context"
	"errors"
	"flag"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/build/internal/gomote/protos"
	"golang.org/x/build/tarutil"
	"golang.org/x/sync/errgroup"
)

// putTar a .tar.gz
func putTar(args []string) error {
	fs := flag.NewFlagSet("put", flag.ContinueOnError)
	fs.Usage = func() {
		fmt.Fprintln(os.Stderr, "puttar usage: gomote puttar [put-opts] [instance] <source>")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "<source> may be one of:")
		fmt.Fprintln(os.Stderr, "- A path to a local .tar.gz file.")
		fmt.Fprintln(os.Stderr, "- A URL that points at a .tar.gz file.")
		fmt.Fprintln(os.Stderr, "- The '-' character to indicate a .tar.gz file passed via stdin.")
		fmt.Fprintln(os.Stderr, "- Git hash (min 7 characters) for the Go repository (extract a .tar.gz of the repository at that commit w/o history)")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Instance name is optional if a group is specified.")
		fs.PrintDefaults()
		os.Exit(1)
	}
	var dir string
	fs.StringVar(&dir, "dir", "", "relative directory from buildlet's work dir to extra tarball into")

	fs.Parse(args)

	// Parse arguments.
	var putSet []string
	var src string
	switch fs.NArg() {
	case 1:
		// Must be just the source, so we need an active group.
		if activeGroup == nil {
			fmt.Fprintln(os.Stderr, "no active group found; need an active group with only 1 argument")
			fs.Usage()
		}
		for _, inst := range activeGroup.Instances {
			putSet = append(putSet, inst)
		}
		src = fs.Arg(0)
	case 2:
		// Instance and source is specified.
		putSet = []string{fs.Arg(0)}
		src = fs.Arg(1)
	case 0:
		fmt.Fprintln(os.Stderr, "error: not enough arguments")
		fs.Usage()
	default:
		fmt.Fprintln(os.Stderr, "error: too many arguments")
		fs.Usage()
	}

	// Interpret source.
	var putTarFn func(ctx context.Context, inst string) error
	if src == "-" {
		// We might have multiple readers, so slurp up STDIN
		// and store it, then hand out bytes.Readers to everyone.
		var buf bytes.Buffer
		_, err := io.Copy(&buf, os.Stdin)
		if err != nil {
			return fmt.Errorf("reading stdin: %w", err)
		}
		sharedTarBuf := buf.Bytes()
		putTarFn = func(ctx context.Context, inst string) error {
			return doPutTar(ctx, inst, dir, bytes.NewReader(sharedTarBuf))
		}
	} else {
		u, err := url.Parse(src)
		if err != nil {
			// The URL parser should technically accept any of these, so the fact that
			// we failed means its *very* malformed.
			return fmt.Errorf("malformed source: not a path, a URL, -, or a git hash")
		}
		if u.Scheme != "" || u.Host != "" {
			// Probably a real URL.
			putTarFn = func(ctx context.Context, inst string) error {
				return doPutTarURL(ctx, inst, dir, u.String())
			}
		} else {
			// Probably a path. Check if it exists.
			_, err := os.Stat(src)
			if os.IsNotExist(err) {
				// It must be a git hash. Check if this actually matches a git hash.
				if len(src) < 7 || len(src) > 40 || regexp.MustCompile("[^a-f0-9]").MatchString(src) {
					return fmt.Errorf("malformed source: not a path, a URL, -, or a git hash")
				}
				putTarFn = func(ctx context.Context, inst string) error {
					return doPutTarGoRev(ctx, inst, dir, src)
				}
			} else if err != nil {
				return fmt.Errorf("failed to stat %q: %w", src, err)
			} else {
				// It's a path.
				putTarFn = func(ctx context.Context, inst string) error {
					f, err := os.Open(src)
					if err != nil {
						return fmt.Errorf("opening %q: %w", src, err)
					}
					defer f.Close()
					return doPutTar(ctx, inst, dir, f)
				}
			}
		}
	}
	eg, ctx := errgroup.WithContext(context.Background())
	for _, inst := range putSet {
		inst := inst
		eg.Go(func() error {
			return putTarFn(ctx, inst)
		})
	}
	return eg.Wait()
}

func doPutTarURL(ctx context.Context, name, dir, tarURL string) error {
	client := gomoteServerClient(ctx)
	_, err := client.WriteTGZFromURL(ctx, &protos.WriteTGZFromURLRequest{
		GomoteId:  name,
		Directory: dir,
		Url:       tarURL,
	})
	if err != nil {
		return fmt.Errorf("unable to write tar to instance: %w", err)
	}
	return nil
}

func doPutTarGoRev(ctx context.Context, name, dir, rev string) error {
	tarURL := "https://go.googlesource.com/go/+archive/" + rev + ".tar.gz"
	if err := doPutTarURL(ctx, name, dir, tarURL); err != nil {
		return err
	}

	// Put a VERSION file there too, to avoid git usage.
	version := strings.NewReader("devel " + rev)
	var vtar tarutil.FileList
	vtar.AddRegular(&tar.Header{
		Name: "VERSION",
		Mode: 0644,
		Size: int64(version.Len()),
	}, int64(version.Len()), version)
	tgz := vtar.TarGz()
	defer tgz.Close()

	client := gomoteServerClient(ctx)
	resp, err := client.UploadFile(ctx, &protos.UploadFileRequest{})
	if err != nil {
		return fmt.Errorf("unable to request credentials for a file upload: %w", err)
	}
	if err := uploadToGCS(ctx, resp.GetFields(), tgz, resp.GetObjectName(), resp.GetUrl()); err != nil {
		return fmt.Errorf("unable to upload version file to GCS: %w", err)
	}
	if _, err = client.WriteTGZFromURL(ctx, &protos.WriteTGZFromURLRequest{
		GomoteId:  name,
		Directory: dir,
		Url:       fmt.Sprintf("%s%s", resp.GetUrl(), resp.GetObjectName()),
	}); err != nil {
		return fmt.Errorf("unable to write tar to instance: %w", err)
	}
	return nil
}

func doPutTar(ctx context.Context, name, dir string, tgz io.Reader) error {
	client := gomoteServerClient(ctx)
	resp, err := client.UploadFile(ctx, &protos.UploadFileRequest{})
	if err != nil {
		return fmt.Errorf("unable to request credentials for a file upload: %w", err)
	}
	if err := uploadToGCS(ctx, resp.GetFields(), tgz, resp.GetObjectName(), resp.GetUrl()); err != nil {
		return fmt.Errorf("unable to upload file to GCS: %w", err)
	}
	if _, err := client.WriteTGZFromURL(ctx, &protos.WriteTGZFromURLRequest{
		GomoteId:  name,
		Directory: dir,
		Url:       fmt.Sprintf("%s%s", resp.GetUrl(), resp.GetObjectName()),
	}); err != nil {
		return fmt.Errorf("unable to write tar to instance: %w", err)
	}
	return nil
}

// putBootstrap places the bootstrap version of go in the workdir
func putBootstrap(args []string) error {
	fs := flag.NewFlagSet("putbootstrap", flag.ContinueOnError)
	fs.Usage = func() {
		fmt.Fprintln(os.Stderr, "putbootstrap usage: gomote putbootstrap [instance]")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Instance name is optional if a group is specified.")
		fs.PrintDefaults()
		os.Exit(1)
	}
	fs.Parse(args)

	var putSet []string
	switch fs.NArg() {
	case 0:
		if activeGroup == nil {
			fmt.Fprintln(os.Stderr, "no active group found; need an active group with only 1 argument")
			fs.Usage()
		}
		for _, inst := range activeGroup.Instances {
			putSet = append(putSet, inst)
		}
	case 1:
		putSet = []string{fs.Arg(0)}
	default:
		fmt.Fprintln(os.Stderr, "error: too many arguments")
		fs.Usage()
	}

	eg, ctx := errgroup.WithContext(context.Background())
	for _, inst := range putSet {
		inst := inst
		eg.Go(func() error {
			client := gomoteServerClient(ctx)
			resp, err := client.AddBootstrap(ctx, &protos.AddBootstrapRequest{
				GomoteId: inst,
			})
			if err != nil {
				return fmt.Errorf("unable to add bootstrap version of Go to instance: %w", err)
			}
			if resp.GetBootstrapGoUrl() == "" {
				fmt.Printf("No GoBootstrapURL defined for %q; ignoring. (may be baked into image)\n", inst)
			}
			return nil
		})
	}
	return eg.Wait()
}

// put single file
func put(args []string) error {
	fs := flag.NewFlagSet("put", flag.ContinueOnError)
	fs.Usage = func() {
		fmt.Fprintln(os.Stderr, "put usage: gomote put [put-opts] [instance] <source or '-' for stdin> [destination]")
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr, "Instance name is optional if a group is specified.")
		fs.PrintDefaults()
		os.Exit(1)
	}
	modeStr := fs.String("mode", "", "Unix file mode (octal); default to source file mode")
	fs.Parse(args)

	if fs.NArg() == 0 {
		fs.Usage()
	}

	ctx := context.Background()
	var putSet []string
	var src, dst string
	if err := doPing(ctx, fs.Arg(0)); instanceDoesNotExist(err) {
		// When there's no active group, this is just an error.
		if activeGroup == nil {
			return fmt.Errorf("instance %q: %w", fs.Arg(0), err)
		}
		// When there is an active group, this just means that we're going
		// to use the group instead and assume the rest is a command.
		for _, inst := range activeGroup.Instances {
			putSet = append(putSet, inst)
		}
		src = fs.Arg(0)
		if fs.NArg() == 2 {
			dst = fs.Arg(1)
		} else if fs.NArg() != 1 {
			fmt.Fprintln(os.Stderr, "error: too many arguments")
			fs.Usage()
		}
	} else if err == nil {
		putSet = append(putSet, fs.Arg(0))
		if fs.NArg() == 1 {
			fmt.Fprintln(os.Stderr, "error: missing source")
			fs.Usage()
		}
		src = fs.Arg(1)
		if fs.NArg() == 3 {
			dst = fs.Arg(2)
		} else if fs.NArg() != 2 {
			fmt.Fprintln(os.Stderr, "error: too many arguments")
			fs.Usage()
		}
	} else {
		return fmt.Errorf("checking instance %q: %w", fs.Arg(0), err)
	}
	if dst == "" {
		if src == "-" {
			return errors.New("must specify destination file name when source is standard input")
		}
		dst = filepath.Base(src)
	}

	var mode os.FileMode = 0666
	if *modeStr != "" {
		modeInt, err := strconv.ParseInt(*modeStr, 8, 64)
		if err != nil {
			return err
		}
		mode = os.FileMode(modeInt)
		if !mode.IsRegular() {
			return fmt.Errorf("bad mode: %v", mode)
		}
	}

	var putFileFn func(context.Context, string) error
	if src == "-" {
		var buf bytes.Buffer
		_, err := io.Copy(&buf, os.Stdin)
		if err != nil {
			return fmt.Errorf("reading from stdin: %w", err)
		}
		sharedFileBuf := buf.Bytes()
		putFileFn = func(ctx context.Context, inst string) error {
			return doPutFile(ctx, inst, bytes.NewReader(sharedFileBuf), dst, mode)
		}
	} else {
		putFileFn = func(ctx context.Context, inst string) error {
			f, err := os.Open(src)
			if err != nil {
				return err
			}
			defer f.Close()

			if *modeStr == "" {
				fi, err := f.Stat()
				if err != nil {
					return err
				}
				mode = fi.Mode()
			}
			return doPutFile(ctx, inst, f, dst, mode)
		}
	}

	eg, ctx := errgroup.WithContext(ctx)
	for _, inst := range putSet {
		inst := inst
		eg.Go(func() error {
			return putFileFn(ctx, inst)
		})
	}
	return eg.Wait()
}

func doPutFile(ctx context.Context, inst string, r io.Reader, dst string, mode os.FileMode) error {
	client := gomoteServerClient(ctx)
	resp, err := client.UploadFile(ctx, &protos.UploadFileRequest{})
	if err != nil {
		return fmt.Errorf("unable to request credentials for a file upload: %w", err)
	}
	err = uploadToGCS(ctx, resp.GetFields(), r, dst, resp.GetUrl())
	if err != nil {
		return fmt.Errorf("unable to upload file to GCS: %w", err)
	}
	_, err = client.WriteFileFromURL(ctx, &protos.WriteFileFromURLRequest{
		GomoteId: inst,
		Url:      fmt.Sprintf("%s%s", resp.GetUrl(), resp.GetObjectName()),
		Filename: dst,
		Mode:     uint32(mode),
	})
	if err != nil {
		return fmt.Errorf("unable to write the file from URL: %w", err)
	}
	return nil
}

func uploadToGCS(ctx context.Context, fields map[string]string, file io.Reader, filename, url string) error {
	buf := new(bytes.Buffer)
	mw := multipart.NewWriter(buf)

	for k, v := range fields {
		if err := mw.WriteField(k, v); err != nil {
			return fmt.Errorf("unable to write field: %w", err)
		}
	}
	_, err := mw.CreateFormFile("file", filename)
	if err != nil {
		return fmt.Errorf("unable to create form file: %w", err)
	}
	// Write our own boundary to avoid buffering entire file into the multipart Writer
	bound := fmt.Sprintf("\r\n--%s--\r\n", mw.Boundary())
	req, err := http.NewRequestWithContext(ctx, "POST", url, io.NopCloser(io.MultiReader(buf, file, strings.NewReader(bound))))
	if err != nil {
		return fmt.Errorf("unable to create request: %w", err)
	}
	req.Header.Set("Content-Type", mw.FormDataContentType())
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("http request failed: %w", err)
	}
	if res.StatusCode != http.StatusNoContent {
		return fmt.Errorf("http post failed: status code=%d", res.StatusCode)
	}
	return nil
}
