// Copyright 2018 Google LLC
//
// 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 cmd contains cos-customizer subcommand implementations.
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"cos.googlesource.com/cos/tools.git/src/pkg/config"
	"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/provisioner"
	"cos.googlesource.com/cos/tools.git/src/pkg/utils"

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

// ServiceClients gets the GCE and GCS clients to use.
type ServiceClients func(ctx context.Context, anonymousCreds bool) (*compute.Service, *storage.Client, error)

// StartImageBuild implements subcommands.Command for the 'start-image-build' command.
// This command initializes a new image customization process.
type StartImageBuild struct {
	buildContext string
	gcsBucket    string
	gcsWorkdir   string
	imageProject string
	imageName    string
	milestone    int
	imageFamily  string
}

// Name implements subcommands.Command.Name.
func (*StartImageBuild) Name() string {
	return "start-image-build"
}

// Synopsis implements subcommands.Command.Synopsis.
func (*StartImageBuild) Synopsis() string {
	return "Start a COS image build."
}

// Usage implements subcommands.Command.Usage.
func (*StartImageBuild) Usage() string {
	return `start-image-build [flags]
`
}

// SetFlags implements subcommands.Command.SetFlags.
func (s *StartImageBuild) SetFlags(f *flag.FlagSet) {
	f.StringVar(&s.buildContext, "build-context", ".", "Path to the build context")
	f.StringVar(&s.gcsBucket, "gcs-bucket", "", "GCS bucket to use for scratch space")
	f.StringVar(&s.gcsWorkdir, "gcs-workdir", "", "GCS directory to use for scratch space")
	f.StringVar(&s.imageProject, "image-project", "", "Source image project")
	f.StringVar(&s.imageName, "image-name", "", "Source image name. Mutually exclusive with 'image-milestone' and "+
		"'image-family'.")
	f.IntVar(&s.milestone, "image-milestone", 0, "Source image milestone. Mutually exclusive with 'image-name' "+
		"and 'image-family'. Can only be used if 'image-project' is cos-cloud.")
	f.StringVar(&s.imageFamily, "image-family", "", "Source image family. Mutually exclusive with 'image-name' "+
		"and 'image-milestone'.")
}

func (s *StartImageBuild) validate() error {
	numSet := 0
	for _, val := range []bool{s.imageName != "", s.milestone != 0, s.imageFamily != ""} {
		if val {
			numSet++
		}
	}
	switch {
	case numSet != 1:
		return fmt.Errorf("exactly one of image-name, image-milestone, image-family must be set")
	case s.milestone != 0 && s.imageProject != "cos-cloud":
		return fmt.Errorf("image-milestone can only be used if image-project is set to cos-cloud. "+
			"image-milestone: %d image-project: %s", s.milestone, s.imageProject)
	case s.gcsBucket == "":
		return fmt.Errorf("gcs-bucket must be set")
	case s.gcsWorkdir == "":
		return fmt.Errorf("gcs-workdir must be set")
	case s.imageProject == "":
		return fmt.Errorf("image-project must be set")
	default:
		return nil
	}
}

func (s *StartImageBuild) resolveImageName(ctx context.Context, svc *compute.Service) error {
	switch {
	case s.milestone != 0:
		var err error
		s.imageName, err = gce.ResolveMilestone(ctx, svc, s.milestone)
		if err != nil {
			if err == gce.ErrImageNotFound {
				return fmt.Errorf("no image found on milestone %d", s.milestone)
			}
			return err
		}
		log.Printf("Using image %s from milestone %d\n", s.imageName, s.milestone)
	case s.imageFamily != "":
		image, err := svc.Images.GetFromFamily(s.imageProject, s.imageFamily).Do()
		if err != nil {
			return err
		}
		s.imageName = image.Name
		log.Printf("Using image %s from family %s\n", s.imageName, s.imageFamily)
	default:
		exists, err := gce.ImageExists(svc, s.imageProject, s.imageName)
		if err != nil {
			return err
		}
		if !exists {
			return fmt.Errorf("could not find source image %s in project %s", s.imageName, s.imageProject)
		}
	}
	return nil
}

func saveImage(imageName, imageProject, dst string) error {
	image := config.NewImage(imageName, imageProject)
	if err := os.MkdirAll(filepath.Dir(dst), 0774); err != nil {
		return err
	}
	outFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer outFile.Close()
	return config.Save(outFile, image)
}

func saveBuildConfig(gcsBucket, gcsWorkdir, dst string) error {
	buildConfig := &config.Build{GCSBucket: gcsBucket, GCSDir: gcsWorkdir}
	if err := os.MkdirAll(filepath.Dir(dst), 0774); err != nil {
		return err
	}
	outFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer outFile.Close()
	return config.SaveConfigToFile(outFile, buildConfig)
}

func saveProvConfig(dst string) (err error) {
	provConfig := &provisioner.Config{}
	if err := os.MkdirAll(filepath.Dir(dst), 0774); err != nil {
		return err
	}
	outFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer utils.CheckClose(outFile, "error closing provisioner config", &err)
	return config.SaveConfigToFile(outFile, provConfig)
}

// Execute implements subcommands.Command.Execute. It initializes persistent state for a new
// image customization process.
func (s *StartImageBuild) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
	if f.NArg() != 0 {
		f.Usage()
		return subcommands.ExitUsageError
	}
	files := args[0].(*fs.Files)
	svc, _, err := args[1].(ServiceClients)(ctx, false)
	if err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := s.validate(); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := s.resolveImageName(ctx, svc); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := fs.CreateBuildContextArchive(s.buildContext, files.UserBuildContextArchive); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := saveImage(s.imageName, s.imageProject, files.SourceImageConfig); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := saveBuildConfig(s.gcsBucket, s.gcsWorkdir, files.BuildConfig); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	if err := saveProvConfig(files.ProvConfig); err != nil {
		log.Println(err)
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}
