// 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 gce contains high-level functionality for manipulating GCE resources.
package gce

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"cos.googlesource.com/cos/tools.git/src/pkg/config"

	compute "google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
)

const (
	defaultOperationTimeout = time.Duration(600) * time.Second
	defaultRetryInterval    = time.Duration(5) * time.Second
	gcsURLPrefix            = "https://storage.googleapis.com"
)

type timePkg struct {
	Now   func() time.Time
	Sleep func(time.Duration)
}

var (
	// ErrTimeout indicates that an operation timed out.
	ErrTimeout = errors.New("operation timed out")

	// ErrImageNotFound indicates that a GCE image could not be found
	ErrImageNotFound = errors.New("image not found")

	realTime = &timePkg{time.Now, time.Sleep}

	// This should match <prefix>-<channel>-<milestone>-<buildnumber>.
	// This is the format of images in cos-cloud.
	// Example: cos-dev-72-11172-0-0
	imageNameRegex = regexp.MustCompile("[a-z0-9-]+-[a-z]+-([0-9]+)-([0-9]+-[0-9]+-[0-9]+)")
)

// buildDeprecationStatus constructs a *compute.DeprecationStatus struct used in a Deprecate GCE API
// call. It fills in the structure with the "DEPRECATED" state, the given replacement, and the given
// delete time, if provided.
func buildDeprecationStatus(replacement string, deleteTime time.Time) *compute.DeprecationStatus {
	status := &compute.DeprecationStatus{State: "DEPRECATED", Replacement: replacement}
	if !deleteTime.IsZero() {
		status.Deleted = deleteTime.Format(time.RFC3339)
	}
	return status
}

func waitForOp(svc *compute.Service, project string, op *compute.Operation, deadline time.Time, t *timePkg) error {
	if op.Error != nil {
		return fmt.Errorf("error with operation. name: %s error: %v", op.Name, op.Error)
	}
	if op.Status == "DONE" {
		return nil
	}
	for {
		t.Sleep(defaultRetryInterval)
		op, err := svc.GlobalOperations.Get(project, op.Name).Do()
		if err != nil {
			return err
		}
		if op.Error != nil {
			return fmt.Errorf("error with operation. name: %s error: %v", op.Name, op.Error)
		}
		if op.Status == "DONE" {
			return nil
		}
		if t.Now().After(deadline) {
			return ErrTimeout
		}
	}
}

func waitForOps(svc *compute.Service, project string, ops []*compute.Operation, t *timePkg) error {
	deadline := t.Now().Add(defaultOperationTimeout)
	for _, op := range ops {
		if err := waitForOp(svc, project, op, deadline, t); err != nil {
			return err
		}
	}
	return nil
}

func deprecateInFamily(ctx context.Context, svc *compute.Service, newImage *config.Image, ttl int, t *timePkg) error {
	if newImage.Family == "" {
		return fmt.Errorf("input image does not have a family for deprecateInFamily. image: %v", newImage)
	}
	filter := fmt.Sprintf("(family = %s) (name != %s)", newImage.Family, newImage.Name)
	images := []*compute.Image{}
	err := svc.Images.List(newImage.Project).Filter(filter).Pages(ctx, func(imageList *compute.ImageList) error {
		images = append(images, imageList.Items...)
		return nil
	})
	if err != nil {
		return err
	}
	ops := []*compute.Operation{}
	for _, image := range images {
		if image.Deprecated != nil {
			continue
		}
		deleteTime := time.Time{}
		if ttl > 0 {
			deleteTime = t.Now().Add(time.Duration(ttl) * time.Second)
		}
		status := buildDeprecationStatus(newImage.URL(), deleteTime)
		op, err := svc.Images.Deprecate(newImage.Project, image.Name, status).Do()
		if err != nil {
			return err
		}
		ops = append(ops, op)
	}
	return waitForOps(svc, newImage.Project, ops, t)
}

// DeprecateInFamily deprecates all of the old images in an image family.
// Allows for assigning TTLs (in seconds) to deprecated images.
func DeprecateInFamily(ctx context.Context, svc *compute.Service, newImage *config.Image, ttl int) error {
	return deprecateInFamily(ctx, svc, newImage, ttl, realTime)
}

// ImageExists checks to see if the given image exists in the given project.
func ImageExists(svc *compute.Service, project, name string) (bool, error) {
	if _, err := svc.Images.Get(project, name).Do(); err != nil {
		if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

// CreateImage creates an image with imageName with the source-url from gcs storage
func CreateImage(svc *compute.Service, sourceURL, imageName, imageProject string) error {
	gcsImageURL := fmt.Sprintf("%s/%s", gcsURLPrefix, sourceURL)
	image := &compute.Image{
		Name: imageName,
		RawDisk: &compute.ImageRawDisk{
			Source: gcsImageURL,
		},
	}
	createImageOp, err := svc.Images.Insert(imageProject, image).Do()
	if err != nil {
		return err
	}
	deadline := time.Now().Add(defaultOperationTimeout)
	return waitForOp(svc, imageProject, createImageOp, deadline, realTime)
}

type decodedImageName struct {
	name        string
	milestone   int
	buildNumber string
}

// newDecodedImageName decodes an image name from cos-cloud and returns
// image information encoded in that image name.
func newDecodedImageName(name string) (*decodedImageName, error) {
	match := imageNameRegex.FindStringSubmatch(name)
	if match == nil {
		return nil, fmt.Errorf("could not parse name %s", name)
	}
	milestone, err := strconv.Atoi(match[1])
	if err != nil {
		return nil, fmt.Errorf("could not convert %s to a milestone: %s", match[1], err)
	}
	return &decodedImageName{name, milestone, match[2]}, nil
}

func imageCompare(first, second *decodedImageName) bool {
	if first.milestone != second.milestone {
		return first.milestone < second.milestone
	}
	for i := 0; i < 3; i++ {
		// Because of how decodedImageNames are created (see newDecodedImageName),
		// these atoi operations are guaranteed to work.
		firstNum, _ := strconv.Atoi(strings.Split(first.buildNumber, "-")[i])
		secondNum, _ := strconv.Atoi(strings.Split(second.buildNumber, "-")[i])
		if firstNum != secondNum {
			return firstNum < secondNum
		}
	}
	return false
}

// ResolveMilestone gets the name of the latest COS image on the given milestone.
// This resolution is done by looking at the image names in cos-cloud.
func ResolveMilestone(ctx context.Context, svc *compute.Service, milestone int) (string, error) {
	var images []*compute.Image
	err := svc.Images.List("cos-cloud").Pages(ctx, func(imageList *compute.ImageList) error {
		images = append(images, imageList.Items...)
		return nil
	})
	if err != nil {
		return "", err
	}
	var inMilestone []*decodedImageName
	for _, image := range images {
		decoded, err := newDecodedImageName(image.Name)
		if err != nil {
			continue
		}
		if decoded.milestone == milestone {
			inMilestone = append(inMilestone, decoded)
		}
	}
	if len(inMilestone) == 0 {
		return "", ErrImageNotFound
	}
	sort.Slice(inMilestone, func(i, j int) bool {
		return imageCompare(inMilestone[i], inMilestone[j])
	})
	return inMilestone[len(inMilestone)-1].name, nil
}
