// Copyright 2020 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 buildlet

import (
	"context"
	"errors"
	"fmt"
	"net"
	"time"

	"golang.org/x/build/buildenv"
	"golang.org/x/build/dashboard"
	"golang.org/x/build/internal/cloud"
)

// awsClient represents the AWS specific calls made durring the
// lifecycle of a buildlet. This is a partial implementation of the AWSClient found at
// `golang.org/x/internal/cloud`.
type awsClient interface {
	Instance(ctx context.Context, instID string) (*cloud.Instance, error)
	CreateInstance(ctx context.Context, config *cloud.EC2VMConfiguration) (*cloud.Instance, error)
	WaitUntilInstanceRunning(ctx context.Context, instID string) error
}

// EC2Client is the client used to create buildlets on EC2.
type EC2Client struct {
	client awsClient
}

// NewEC2Client creates a new EC2Client.
func NewEC2Client(client *cloud.AWSClient) *EC2Client {
	return &EC2Client{
		client: client,
	}
}

// StartNewVM boots a new VM on EC2, waits until the client is accepting connections
// on the configured port and returns a buildlet client configured communicate with it.
func (c *EC2Client) StartNewVM(ctx context.Context, buildEnv *buildenv.Environment, hconf *dashboard.HostConfig, vmName, hostType string, opts *VMOpts) (*Client, error) {
	// check required params
	if opts == nil || opts.TLS.IsZero() {
		return nil, errors.New("TLS keypair is not set")
	}
	if buildEnv == nil {
		return nil, errors.New("invalid build enviornment")
	}
	if hconf == nil {
		return nil, errors.New("invalid host configuration")
	}
	if vmName == "" || hostType == "" {
		return nil, fmt.Errorf("invalid vmName: %q and hostType: %q", vmName, hostType)
	}

	// configure defaults
	if opts.Description == "" {
		opts.Description = fmt.Sprintf("Go Builder for %s", hostType)
	}
	if opts.DeleteIn == 0 {
		opts.DeleteIn = 30 * time.Minute
	}

	vmConfig := configureVM(buildEnv, hconf, vmName, hostType, opts)

	vm, err := c.createVM(ctx, vmConfig, opts)
	if err != nil {
		return nil, err
	}
	if err = c.waitUntilVMExists(ctx, vm.ID, opts); err != nil {
		return nil, err
	}
	// once the VM is up and running then all of the configuration data is available
	// when the API is querried for the VM.
	vm, err = c.client.Instance(ctx, vm.ID)
	if err != nil {
		return nil, fmt.Errorf("unable to retrieve instance %q information: %w", vm.ID, err)
	}
	buildletURL, ipPort, err := ec2BuildletParams(vm, opts)
	if err != nil {
		return nil, err
	}
	return buildletClient(ctx, buildletURL, ipPort, opts)
}

// createVM submits a request for the creation of a VM.
func (c *EC2Client) createVM(ctx context.Context, config *cloud.EC2VMConfiguration, opts *VMOpts) (*cloud.Instance, error) {
	if config == nil || opts == nil {
		return nil, errors.New("invalid parameter")
	}
	inst, err := c.client.CreateInstance(ctx, config)
	if err != nil {
		return nil, fmt.Errorf("unable to create instance: %w", err)
	}
	condRun(opts.OnInstanceRequested)
	return inst, nil
}

// waitUntilVMExists submits a request which waits until an instance exists before returning.
func (c *EC2Client) waitUntilVMExists(ctx context.Context, instID string, opts *VMOpts) error {
	if err := c.client.WaitUntilInstanceRunning(ctx, instID); err != nil {
		return fmt.Errorf("failed waiting for vm instance: %w", err)
	}
	condRun(opts.OnInstanceCreated)
	return nil
}

// configureVM creates a configuration for an EC2 VM instance.
func configureVM(buildEnv *buildenv.Environment, hconf *dashboard.HostConfig, vmName, hostType string, opts *VMOpts) *cloud.EC2VMConfiguration {
	return &cloud.EC2VMConfiguration{
		Description:    opts.Description,
		ImageID:        hconf.VMImage,
		Name:           vmName,
		SSHKeyID:       "ec2-go-builders",
		SecurityGroups: []string{buildEnv.AWSSecurityGroup},
		Tags:           make(map[string]string),
		Type:           hconf.MachineType(),
		UserData:       vmUserDataSpec(buildEnv, hconf, vmName, hostType, opts),
		Zone:           opts.Zone,
	}
}

func vmUserDataSpec(buildEnv *buildenv.Environment, hconf *dashboard.HostConfig, vmName, hostType string, opts *VMOpts) string {
	// add custom metadata to the user data.
	ud := cloud.EC2UserData{
		BuildletName:      vmName,
		BuildletBinaryURL: hconf.BuildletBinaryURL(buildEnv),
		BuildletHostType:  hostType,
		BuildletImageURL:  hconf.ContainerVMImage(),
		Metadata:          make(map[string]string),
		TLSCert:           opts.TLS.CertPEM,
		TLSKey:            opts.TLS.KeyPEM,
		TLSPassword:       opts.TLS.Password(),
	}
	for k, v := range opts.Meta {
		ud.Metadata[k] = v
	}
	return ud.EncodedString()
}

// ec2BuildletParams returns the necessary information to connect to an EC2 buildlet. A
// buildlet URL and an IP address port are required to connect to a buildlet.
func ec2BuildletParams(inst *cloud.Instance, opts *VMOpts) (string, string, error) {
	if inst.IPAddressExternal == "" {
		return "", "", errors.New("external IP address is not set")
	}
	extIP := inst.IPAddressExternal
	buildletURL := fmt.Sprintf("https://%s", extIP)
	ipPort := net.JoinHostPort(extIP, "443")

	if opts.OnGotEC2InstanceInfo != nil {
		opts.OnGotEC2InstanceInfo(inst)
	}
	return buildletURL, ipPort, nil
}
