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

import (
	"context"
	"crypto/rand"
	"errors"
	"fmt"
	mrand "math/rand"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go/service/ec2"
)

func init() { mrand.Seed(time.Now().UnixNano()) }

// FakeAWSClient provides a fake AWS Client used to test the AWS client
// functionality.
type FakeAWSClient struct {
	mu            sync.RWMutex
	instances     map[string]*Instance
	instanceTypes []*InstanceType
	serviceQuotas map[serviceQuotaKey]int64
}

// serviceQuotaKey should be used as the key in the serviceQuotas map.
type serviceQuotaKey struct {
	code    string
	service string
}

// NewFakeAWSClient crates a fake AWS client.
func NewFakeAWSClient() *FakeAWSClient {
	return &FakeAWSClient{
		instances: make(map[string]*Instance),
		instanceTypes: []*InstanceType{
			&InstanceType{"ab.large", 10},
			&InstanceType{"ab.xlarge", 20},
			&InstanceType{"ab.small", 30},
		},
		serviceQuotas: map[serviceQuotaKey]int64{
			serviceQuotaKey{QuotaCodeCPUOnDemand, QuotaServiceEC2}: 384,
		},
	}
}

// Instance returns the `Instance` record for the rquested instance. The instance record will
// return records for recently terminated instances. If an instance is not found an error will
// be returned.
func (f *FakeAWSClient) Instance(ctx context.Context, instID string) (*Instance, error) {
	if ctx == nil || instID == "" {
		return nil, errors.New("invalid params")
	}
	f.mu.RLock()
	defer f.mu.RUnlock()

	inst, ok := f.instances[instID]
	if !ok {
		return nil, errors.New("instance not found")
	}
	return copyInstance(inst), nil
}

// Instances retrieves all EC2 instances in a region which have not been terminated or stopped.
func (f *FakeAWSClient) RunningInstances(ctx context.Context) ([]*Instance, error) {
	if ctx == nil {
		return nil, errors.New("invalid params")
	}
	f.mu.RLock()
	defer f.mu.RUnlock()

	instances := make([]*Instance, 0, len(f.instances))
	for _, inst := range f.instances {
		if inst.State != ec2.InstanceStateNameRunning && inst.State != ec2.InstanceStateNamePending {
			continue
		}
		instances = append(instances, copyInstance(inst))
	}
	return instances, nil
}

// InstanceTypesArm retrieves all EC2 instance types in a region which support the ARM64 architecture.
func (f *FakeAWSClient) InstanceTypesARM(ctx context.Context) ([]*InstanceType, error) {
	if ctx == nil {
		return nil, errors.New("invalid params")
	}
	f.mu.RLock()
	defer f.mu.RUnlock()

	instanceTypes := make([]*InstanceType, 0, len(f.instanceTypes))
	for _, it := range f.instanceTypes {
		instanceTypes = append(instanceTypes, &InstanceType{it.Type, it.CPU})
	}
	return instanceTypes, nil
}

// Quota retrieves the requested service quota for the service.
func (f *FakeAWSClient) Quota(ctx context.Context, service, code string) (int64, error) {
	if ctx == nil || service == "" || code == "" {
		return 0, errors.New("invalid params")
	}
	f.mu.RLock()
	defer f.mu.RUnlock()

	v, ok := f.serviceQuotas[serviceQuotaKey{code, service}]
	if !ok {
		return 0, errors.New("service quota not found")
	}
	return v, nil
}

// CreateInstance creates an EC2 VM instance.
func (f *FakeAWSClient) CreateInstance(ctx context.Context, config *EC2VMConfiguration) (*Instance, error) {
	if ctx == nil || config == nil {
		return nil, errors.New("invalid params")
	}
	if config.ImageID == "" {
		return nil, errors.New("invalid Image ID")
	}
	if config.Type == "" {
		return nil, errors.New("invalid Type")
	}
	if config.Zone == "" {
		return nil, errors.New("invalid Zone")
	}
	f.mu.Lock()
	defer f.mu.Unlock()

	inst := &Instance{
		CPUCount:          4,
		CreatedAt:         time.Now(),
		Description:       config.Description,
		ID:                fmt.Sprintf("instance-%s", randHex(10)),
		IPAddressExternal: randIPv4(),
		IPAddressInternal: randIPv4(),
		ImageID:           config.ImageID,
		Name:              config.Name,
		SSHKeyID:          config.SSHKeyID,
		SecurityGroups:    config.SecurityGroups,
		State:             ec2.InstanceStateNameRunning,
		Tags:              make(map[string]string),
		Type:              config.Type,
		Zone:              config.Zone,
	}
	for k, v := range config.Tags {
		inst.Tags[k] = v
	}
	f.instances[inst.ID] = inst
	return copyInstance(inst), nil
}

// DestroyInstances terminates EC2 VM instances.
func (f *FakeAWSClient) DestroyInstances(ctx context.Context, instIDs ...string) error {
	if ctx == nil || len(instIDs) == 0 {
		return errors.New("invalid params")
	}
	f.mu.Lock()
	defer f.mu.Unlock()

	for _, id := range instIDs {
		inst, ok := f.instances[id]
		if !ok {
			return errors.New("instance not found")
		}
		inst.State = ec2.InstanceStateNameTerminated
	}
	return nil
}

// WaitUntilInstanceRunning returns when an instance has transitioned into the running state.
func (f *FakeAWSClient) WaitUntilInstanceRunning(ctx context.Context, instID string) error {
	if ctx == nil || instID == "" {
		return errors.New("invalid params")
	}
	f.mu.RLock()
	defer f.mu.RUnlock()

	inst, ok := f.instances[instID]
	if !ok {
		return errors.New("instance not found")
	}
	if inst.State != ec2.InstanceStateNameRunning {
		return errors.New("timed out waiting for instance to enter running state")
	}
	return nil
}

// copyInstance copies the contents of a pointer to an instance and returns a newly created
// instance with the same data as the original instance.
func copyInstance(inst *Instance) *Instance {
	i := &Instance{
		CPUCount:          inst.CPUCount,
		CreatedAt:         inst.CreatedAt,
		Description:       inst.Description,
		ID:                inst.ID,
		IPAddressExternal: inst.IPAddressExternal,
		IPAddressInternal: inst.IPAddressInternal,
		ImageID:           inst.ImageID,
		Name:              inst.Name,
		SSHKeyID:          inst.SSHKeyID,
		SecurityGroups:    inst.SecurityGroups,
		State:             inst.State,
		Tags:              make(map[string]string),
		Type:              inst.Type,
		Zone:              inst.Zone,
	}
	for k, v := range inst.Tags {
		i.Tags[k] = v
	}
	return i
}

// randHex creates a random hex string of length n.
func randHex(n int) string {
	buf := make([]byte, n/2+1)
	_, _ = rand.Read(buf)
	return fmt.Sprintf("%x", buf)[:n]
}

// randIPv4 creates a random IPv4 address.
func randIPv4() string {
	return fmt.Sprintf("%d.%d.%d.%d", mrand.Intn(255), mrand.Intn(255), mrand.Intn(255), mrand.Intn(255))
}
