// Copyright 2021 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ovaconverter

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

	"cloud.google.com/go/storage"
	"github.com/golang/glog"
	"google.golang.org/api/compute/v1"

	"cos.googlesource.com/cos/tools.git/src/pkg/fs"
	"cos.googlesource.com/cos/tools.git/src/pkg/gce"
	"cos.googlesource.com/cos/tools.git/src/pkg/gcs"
	"cos.googlesource.com/cos/tools.git/src/pkg/utils"
)

const (
	vmdkFileExtension = ".vmdk"
)

type Converter struct {
	GCSClient      *storage.Client
	ComputeService *compute.Service
}

func NewConverter(ctx context.Context) *Converter {
	gcsClient, err := storage.NewClient(ctx)
	if err != nil {
		return nil
	}
	svc, err := compute.NewService(ctx)
	if err != nil {
		return nil
	}
	return &Converter{
		GCSClient:      gcsClient,
		ComputeService: svc,
	}
}

// ConvertOVAToGCE converts the OVA file at GCS Location to a GCE image.
func (converter *Converter) ConvertOVAToGCE(ctx context.Context, inputURL, imageName, gcsBucket, imageProject string) error {
	// Create a temporary working directory
	tempWorkDir, err := os.MkdirTemp("", "ova_dir")
	if err != nil {
		return err
	}
	defer utils.RemoveDir(tempWorkDir, "error on removing the temporary working directory", nil)

	glog.Info("Downloading OVA from the input GCS URL")
	inputFile := filepath.Join(tempWorkDir, "input.ova")
	if err = gcs.DownloadGCSObject(ctx, converter.GCSClient,
		inputURL, inputFile); err != nil {
		return err
	}

	extractWorkDir := filepath.Join(tempWorkDir, "extractWorkDir")
	glog.Info("Converting OVA to VMDK...")
	if err = fs.ExtractFile(inputFile, extractWorkDir); err != nil {
		return err
	}

	var vmdkFile string
	files, _ := ioutil.ReadDir(extractWorkDir)
	for _, file := range files {
		if filepath.Ext(file.Name()) == vmdkFileExtension {
			vmdkFile = file.Name()
			break
		}
	}

	glog.Info("Converting VMDK to Raw...")
	tempRawImage := filepath.Join(tempWorkDir, "disk.raw")
	if err = utils.ConvertImageToRaw(filepath.Join(extractWorkDir,
		vmdkFile), tempRawImage); err != nil {
		return err
	}

	cosGCETar := fmt.Sprintf("%s_gce.tar.gz", imageName)

	glog.Info("Compressing disk.raw to tar.gz...")
	if err = fs.TarFile(tempRawImage, filepath.Join(tempWorkDir, cosGCETar)); err != nil {
		return err
	}

	cosTarURL := fmt.Sprintf("gs://%s/%s", gcsBucket, cosGCETar)

	glog.Info("Uploading tar.gz file to a remote GCS location...")
	if err = gcs.UploadGCSObject(ctx, converter.GCSClient, filepath.Join(tempWorkDir, cosGCETar), cosTarURL); err != nil {
		return err
	}
	// delete the image staged temporarily before creating a GCE image
	defer func() {
		if gcs.DeleteGCSObject(ctx, converter.GCSClient, cosTarURL); err != nil {
			glog.Warningf("error deleting the GCS temporary Object: %v", err)
		}
	}()

	glog.Info("Creating a GCS Image...")
	return gce.CreateImage(converter.ComputeService, filepath.Join(gcsBucket, cosGCETar),
		imageName, imageProject)

}

// ConvertOVAFromGCE converts GCE Image to OVA Format.
func (converter *Converter) ConvertOVAFromGCE(ctx context.Context, sourceImage, destinationPath, gcsBucket, imageProject, zone string,
	gceToOVAConverterConfig *GCEToOVAConverterConfig) error {
	tempWorkDir, err := ioutil.TempDir("", "ovaDir")
	if err != nil {
		return err
	}
	defer utils.RemoveDir(tempWorkDir, "error on removing the temporary working directory", nil)

	tempExportedImageName := fmt.Sprintf("%s-exported-image.tar.gz", sourceImage)
	tempExportImageURL := fmt.Sprintf("gs://%s/%s", gcsBucket, tempExportedImageName)

	glog.Info("Exporting image in tar.gz format to a temporary GCS location")
	// Export the GCE image to a temporary location
	if err = exportImageFromGCEUsingDaisy(sourceImage, imageProject, tempExportImageURL, zone,
		gceToOVAConverterConfig.DaisyBin, gceToOVAConverterConfig.DaisyWorkflowPath); err != nil {
		return err
	}

	glog.Info("Downloading the image in tar.gz...")
	downloadImagePath := filepath.Join(tempWorkDir, tempExportedImageName)
	if err = gcs.DownloadGCSObject(ctx, converter.GCSClient,
		tempExportImageURL, downloadImagePath); err != nil {
		return err
	}

	defer func() {
		if err = gcs.DeleteGCSObject(ctx, converter.GCSClient, tempExportImageURL); err != nil {
			glog.Warningf("error deleting the GCS temporary Object: %v", err)

		}
	}()

	glog.Info("Extracting the disk.raw image from the tar file...")
	extractWorkDir := filepath.Join(tempWorkDir, "extractDir")
	if err = fs.ExtractFile(downloadImagePath, extractWorkDir); err != nil {
		return err
	}

	glog.Info("Converting the disk.raw image to vmdk format...")
	tempVMDKImageName := filepath.Join(tempWorkDir, "chromiumos_image.vmdk")
	if err = utils.ConvertImageToVMDK(filepath.Join(extractWorkDir, "disk.raw"), tempVMDKImageName); err != nil {
		return err
	}

	// convert to OVA image
	glog.Info("Converting the VMDK to OVA image...")
	tempOVAImage := filepath.Join(tempWorkDir, filepath.Base(destinationPath))
	oVAImageName := strings.ReplaceAll(filepath.Base(destinationPath),
		filepath.Ext(filepath.Base(destinationPath)), "")
	if err = utils.RunCommand([]string{
		gceToOVAConverterConfig.MakeOVAScript,
		"-d", tempVMDKImageName, "-o", tempOVAImage, "-p", "GKE On-Prem", "-n",
		oVAImageName, "-t", gceToOVAConverterConfig.OVATemplate,
	}, "", nil); err != nil {
		return err
	}

	glog.Info("Uploading the OVA file to the GCS URL...")
	if err = gcs.UploadGCSObject(ctx, converter.GCSClient, tempOVAImage,
		destinationPath); err != nil {
		return err
	}
	return nil
}

// exportImageFromGCEUsingDaisy exports an image to the gce.tar.gz file by initiating a
// daisy workflow.
// Input: daisyBin - path to the daisy binary, daisyWorkflowPath - path to the image exporter workflow.
func exportImageFromGCEUsingDaisy(imageName, imageProject, destinationFile, zone, daisyBin, daisyWorkflowPath string) error {
	sourceImage := fmt.Sprintf("-var:source_image=projects/%s/global/images/%s", imageProject, imageName)
	destination := fmt.Sprintf("-var:destination=%s", destinationFile)
	exportImageUsingDaisyCommand := []string{
		daisyBin, "-project", imageProject, "-zone", zone, sourceImage, destination, daisyWorkflowPath,
	}
	return utils.RunCommand(exportImageUsingDaisyCommand, "", nil)
}
