// 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.DownloadGCSObjectFromURL(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.DownloadGCSObjectFromURL(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)
}
