// Copyright 2022 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
//
//     https://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.

// Code generated by protoc-gen-go_gapic. DO NOT EDIT.

package compute

import (
	"context"
	"time"

	gax "github.com/googleapis/gax-go/v2"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

// Operation represents a long-running operation for this API.
type Operation struct {
	operationHandle
}

// Done reports whether the long-running operation has completed.
func (o *Operation) Done() bool {
	return o.Proto().GetStatus() == computepb.Operation_DONE
}

// Name returns the name of the long-running operation.
// The name is assigned by the server and is unique within the service from which the operation is created.
func (o *Operation) Name() string {
	return o.Proto().GetName()
}

// Wait blocks until the operation is complete, polling regularly
// after an intial period of backing off between attempts.
func (o *Operation) Wait(ctx context.Context, opts ...gax.CallOption) error {
	bo := gax.Backoff{
		Initial: time.Second,
		Max:     time.Minute,
	}
	for {
		if err := o.Poll(ctx, opts...); err != nil {
			return err
		}
		if o.Done() {
			return nil
		}
		if err := gax.Sleep(ctx, bo.Pause()); err != nil {
			return err
		}
	}
}

type operationHandle interface {
	// Poll retrieves the operation.
	Poll(ctx context.Context, opts ...gax.CallOption) error

	// Proto returns the long-running operation message.
	Proto() *computepb.Operation
}

// Implements the operationHandle interface for RegionOperations.
type regionOperationsHandle struct {
	c       *RegionOperationsClient
	proto   *computepb.Operation
	project string
	region  string
}

// Poll retrieves the latest data for the long-running operation.
func (h *regionOperationsHandle) Poll(ctx context.Context, opts ...gax.CallOption) error {
	resp, err := h.c.Get(ctx, &computepb.GetRegionOperationRequest{
		Operation: h.proto.GetName(),
		Project:   h.project,
		Region:    h.region,
	}, opts...)
	if err != nil {
		return err
	}
	h.proto = resp
	return nil
}

// Proto returns the raw type this wraps.
func (h *regionOperationsHandle) Proto() *computepb.Operation {
	return h.proto
}

// Implements the operationHandle interface for ZoneOperations.
type zoneOperationsHandle struct {
	c       *ZoneOperationsClient
	proto   *computepb.Operation
	project string
	zone    string
}

// Poll retrieves the latest data for the long-running operation.
func (h *zoneOperationsHandle) Poll(ctx context.Context, opts ...gax.CallOption) error {
	resp, err := h.c.Get(ctx, &computepb.GetZoneOperationRequest{
		Operation: h.proto.GetName(),
		Project:   h.project,
		Zone:      h.zone,
	}, opts...)
	if err != nil {
		return err
	}
	h.proto = resp
	return nil
}

// Proto returns the raw type this wraps.
func (h *zoneOperationsHandle) Proto() *computepb.Operation {
	return h.proto
}

// Implements the operationHandle interface for GlobalOperations.
type globalOperationsHandle struct {
	c       *GlobalOperationsClient
	proto   *computepb.Operation
	project string
}

// Poll retrieves the latest data for the long-running operation.
func (h *globalOperationsHandle) Poll(ctx context.Context, opts ...gax.CallOption) error {
	resp, err := h.c.Get(ctx, &computepb.GetGlobalOperationRequest{
		Operation: h.proto.GetName(),
		Project:   h.project,
	}, opts...)
	if err != nil {
		return err
	}
	h.proto = resp
	return nil
}

// Proto returns the raw type this wraps.
func (h *globalOperationsHandle) Proto() *computepb.Operation {
	return h.proto
}

// Implements the operationHandle interface for GlobalOrganizationOperations.
type globalOrganizationOperationsHandle struct {
	c     *GlobalOrganizationOperationsClient
	proto *computepb.Operation
}

// Poll retrieves the latest data for the long-running operation.
func (h *globalOrganizationOperationsHandle) Poll(ctx context.Context, opts ...gax.CallOption) error {
	resp, err := h.c.Get(ctx, &computepb.GetGlobalOrganizationOperationRequest{
		Operation: h.proto.GetName(),
	}, opts...)
	if err != nil {
		return err
	}
	h.proto = resp
	return nil
}

// Proto returns the raw type this wraps.
func (h *globalOrganizationOperationsHandle) Proto() *computepb.Operation {
	return h.proto
}
