package cos

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"cloud.google.com/go/compute/metadata"
	"cloud.google.com/go/storage"
	"cos.googlesource.com/cos/tools.git/src/pkg/gcs"
	"github.com/golang/glog"
	log "github.com/golang/glog"
	"github.com/pkg/errors"
)

const (
	cosToolsGCS      = "cos-tools"
	cosToolsGCSAsia  = "cos-tools-asia"
	cosToolsGCSEU    = "cos-tools-eu"
	kernelInfo       = "kernel_info"
	kernelSrcArchive = "kernel-src.tar.gz"
	kernelHeaders    = "kernel-headers.tgz"
	toolchainURL     = "toolchain_url"
	toolchainArchive = "toolchain.tar.xz"
	toolchainEnv     = "toolchain_env"
	crosKernelRepo   = "https://chromium.googlesource.com/chromiumos/third_party/kernel"
)

// Map VM zone prefix to specific cos-tools bucket for geo-redundancy.
var cosToolsPrefixMap = map[string]string{
	"us":           cosToolsGCS,
	"northamerica": cosToolsGCS,
	"southamerica": cosToolsGCS,
	"europe":       cosToolsGCSEU,
	"asia":         cosToolsGCSAsia,
	"australia":    cosToolsGCSAsia,
}

// ArtifactsDownloader defines the interface to download COS artifacts.
type ArtifactsDownloader interface {
	DownloadKernelSrc(ctx context.Context, destDir string) error
	DownloadToolchainEnv(ctx context.Context, destDir string) error
	DownloadToolchain(ctx context.Context, destDir string) error
	DownloadKernelHeaders(dctx context.Context, estDir string) error
	DownloadArtifact(ctx context.Context, destDir, artifact string) error
	GetArtifact(ctx context.Context, artifact string) ([]byte, error)
	ArtifactExists(ctx context.Context, artifact string) (bool, error)
}

// GCSDownloader is the struct downloading COS artifacts from GCS bucket.
type GCSDownloader struct {
	gcsClient         *storage.Client
	envReader         *EnvReader
	gcsDownloadBucket string
	gcsDownloadPrefix string
}

// NewGCSDownloader creates a GCSDownloader instance.
func NewGCSDownloader(gcsClient *storage.Client, e *EnvReader, bucket, prefix string) *GCSDownloader {
	// If bucket is not set, use cos-tools, cos-tools-asia or cos-tools-eu
	// according to the zone the VM is running in for geo-redundancy.
	// If cannot fetch zone from metadata or get an unknown zone prefix,
	// use cos-tools as the default GCS bucket.
	if bucket == "" {
		zone, err := metadata.Zone()
		if err != nil {
			log.Warningf("failed to get zone from metadata, will use 'gs://cos-tools' as artifact bucket, err: %v", err)
			bucket = cosToolsGCS
		} else {
			zonePrefix := strings.Split(zone, "-")[0]
			if geoBucket, found := cosToolsPrefixMap[zonePrefix]; found {
				bucket = geoBucket
			} else {
				bucket = cosToolsGCS
			}
		}
	}
	// Use {build number}/{board} as the default GCS download prefix.
	if prefix == "" {
		prefix = path.Join(e.BuildNumber(), e.Board())
	}
	return &GCSDownloader{gcsClient, e, bucket, prefix}
}

// DownloadKernelSrc downloads COS kernel sources to destination directory.
func (d *GCSDownloader) DownloadKernelSrc(ctx context.Context, destDir string) error {
	return d.DownloadArtifact(ctx, destDir, kernelSrcArchive)
}

// DownloadToolchainEnv downloads toolchain compilation environment variables to destination directory.
func (d *GCSDownloader) DownloadToolchainEnv(ctx context.Context, destDir string) error {
	return d.DownloadArtifact(ctx, destDir, toolchainEnv)
}

// DownloadToolchain downloads toolchain package to destination directory.
func (d *GCSDownloader) DownloadToolchain(ctx context.Context, destDir string) error {
	return d.DownloadArtifact(ctx, destDir, toolchainArchive)
}

// DownloadKernelHeaders downloads COS kernel headers to destination directory.
func (d *GCSDownloader) DownloadKernelHeaders(ctx context.Context, destDir string) error {
	return d.DownloadArtifact(ctx, destDir, kernelHeaders)
}

// GetArtifact gets an artifact from GCS buckets and returns its content.
func (d *GCSDownloader) GetArtifact(ctx context.Context, artifactPath string) ([]byte, error) {
	tmpDir, err := ioutil.TempDir("", "tmp")
	if err != nil {
		return nil, errors.Wrap(err, "failed to create temp dir")
	}
	defer os.RemoveAll(tmpDir)

	if err = d.DownloadArtifact(ctx, tmpDir, artifactPath); err != nil {
		return nil, errors.Wrapf(err, "failed to download artifact %s", artifactPath)
	}

	content, err := ioutil.ReadFile(filepath.Join(tmpDir, filepath.Base(artifactPath)))
	if err != nil {
		return nil, errors.Wrapf(err, "failed to read file %s", filepath.Join(tmpDir, artifactPath))
	}

	return content, nil
}

// DownloadArtifact downloads an artifact from the GCS prefix configured in GCSDownloader.
func (d *GCSDownloader) DownloadArtifact(ctx context.Context, destDir, artifactPath string) error {
	gcsPath := path.Join(d.gcsDownloadPrefix, artifactPath)
	filename := filepath.Base(gcsPath)
	outputPath := filepath.Join(destDir, filename)
	glog.Infof("Start to download %s artifact from bucket: %s, object: %s to %s.", filename, d.gcsDownloadBucket, gcsPath, outputPath)
	if err := gcs.DownloadGCSObject(ctx, d.gcsClient, d.gcsDownloadBucket, gcsPath, outputPath); err != nil {
		glog.Errorf("Failed to download %s artifact from bucket: %s, object: %s to %s with error: %v.", filename, d.gcsDownloadBucket, gcsPath, outputPath, err)
		return fmt.Errorf("failed to download %s artifact from bucket: %s, object: %s to %s with error: %w", filename, d.gcsDownloadBucket, gcsPath, outputPath, err)
	}
	glog.Infof("Sucessfully downloaded %s artifact from bucket: %s, object: %s to %s.", filename, d.gcsDownloadBucket, gcsPath, outputPath)
	return nil

}

// ArtifactExists check whether the artifactpath exists.
func (d *GCSDownloader) ArtifactExists(ctx context.Context, artifactPath string) (bool, error) {
	gcsPath := path.Join(d.gcsDownloadPrefix, artifactPath)
	glog.Infof("Start to check whether artifact: %s exists in bucket: %s", gcsPath, d.gcsDownloadBucket)
	exists, error := gcs.GCSObjectExists(ctx, d.gcsClient, d.gcsDownloadBucket, gcsPath)
	if error != nil {
		glog.Errorf("Error appears when using gcs to check whether artifact: %s exists in bucket: %s - %v", gcsPath, d.gcsDownloadBucket, error)
		return false, fmt.Errorf("error appears when using gcs to check whether artifact: %s exists in bucket: %s - %w", gcsPath, d.gcsDownloadBucket, error)
	}
	return exists, nil
}
