// Copyright 2016 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 longrunning supports Long Running Operations for the Google Cloud Libraries.
// See google.golang.org/genproto/googleapis/longrunning for its service definition.
//
// Users of the Google Cloud Libraries will typically not use this package directly.
// Instead they will call functions returning Operations and call their methods.
//
// This package is still experimental and subject to change.
package longrunning // import "cloud.google.com/go/longrunning"

import (
	"context"
	"errors"
	"fmt"
	"time"

	autogen "cloud.google.com/go/longrunning/autogen"
	pb "cloud.google.com/go/longrunning/autogen/longrunningpb"
	gax "github.com/googleapis/gax-go/v2"
	"github.com/googleapis/gax-go/v2/apierror"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/protoadapt"
	"google.golang.org/protobuf/types/known/anypb"
)

// ErrNoMetadata is the error returned by Metadata if the operation contains no metadata.
var ErrNoMetadata = errors.New("operation contains no metadata")

// Operation represents the result of an API call that may not be ready yet.
type Operation struct {
	c     operationsClient
	proto *pb.Operation
}

type operationsClient interface {
	GetOperation(context.Context, *pb.GetOperationRequest, ...gax.CallOption) (*pb.Operation, error)
	CancelOperation(context.Context, *pb.CancelOperationRequest, ...gax.CallOption) error
	DeleteOperation(context.Context, *pb.DeleteOperationRequest, ...gax.CallOption) error
}

// InternalNewOperation is for use by the google Cloud Libraries only.
//
// InternalNewOperation returns an long-running operation, abstracting the raw pb.Operation.
// The conn parameter refers to a server that proto was received from.
func InternalNewOperation(inner *autogen.OperationsClient, proto *pb.Operation) *Operation {
	return &Operation{
		c:     inner,
		proto: proto,
	}
}

// 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 (op *Operation) Name() string {
	return op.proto.Name
}

// Done reports whether the long-running operation has completed.
func (op *Operation) Done() bool {
	return op.proto.Done
}

// Metadata unmarshals op's metadata into meta.
// If op does not contain any metadata, Metadata returns ErrNoMetadata and meta is unmodified.
func (op *Operation) Metadata(meta protoadapt.MessageV1) error {
	if m := op.proto.Metadata; m != nil {
		metav2 := protoadapt.MessageV2Of(meta)
		return anypb.UnmarshalTo(m, metav2, proto.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true})
	}
	return ErrNoMetadata
}

// Poll fetches the latest state of a long-running operation.
//
// If Poll fails, the error is returned and op is unmodified.
// If Poll succeeds and the operation has completed with failure,
// the error is returned and op.Done will return true.
// If Poll succeeds and the operation has completed successfully,
// op.Done will return true; if resp != nil, the response of the operation
// is stored in resp.
func (op *Operation) Poll(ctx context.Context, resp protoadapt.MessageV1, opts ...gax.CallOption) error {
	if !op.Done() {
		p, err := op.c.GetOperation(ctx, &pb.GetOperationRequest{Name: op.Name()}, opts...)
		if err != nil {
			return err
		}
		op.proto = p
	}
	if !op.Done() {
		return nil
	}

	switch r := op.proto.Result.(type) {
	case *pb.Operation_Error:
		err, _ := apierror.FromError(status.ErrorProto(r.Error))
		return err
	case *pb.Operation_Response:
		if resp == nil {
			return nil
		}
		respv2 := protoadapt.MessageV2Of(resp)
		return anypb.UnmarshalTo(r.Response, respv2, proto.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true})
	default:
		return fmt.Errorf("unsupported result type %[1]T: %[1]v", r)
	}
}

// DefaultWaitInterval is the polling interval used by Operation.Wait.
const DefaultWaitInterval = 60 * time.Second

// Wait is equivalent to WaitWithInterval using DefaultWaitInterval.
func (op *Operation) Wait(ctx context.Context, resp protoadapt.MessageV1, opts ...gax.CallOption) error {
	return op.WaitWithInterval(ctx, resp, DefaultWaitInterval, opts...)
}

// WaitWithInterval blocks until the operation is completed.
// If resp != nil, Wait stores the response in resp.
// WaitWithInterval polls every interval, except initially
// when it polls using exponential backoff.
//
// See documentation of Poll for error-handling information.
func (op *Operation) WaitWithInterval(ctx context.Context, resp protoadapt.MessageV1, interval time.Duration, opts ...gax.CallOption) error {
	bo := gax.Backoff{
		Initial: 1 * time.Second,
		Max:     interval,
	}
	if bo.Max < bo.Initial {
		bo.Max = bo.Initial
	}
	return op.wait(ctx, resp, &bo, gax.Sleep, opts...)
}

type sleeper func(context.Context, time.Duration) error

// wait implements Wait, taking exponentialBackoff and sleeper arguments for testing.
func (op *Operation) wait(ctx context.Context, resp protoadapt.MessageV1, bo *gax.Backoff, sl sleeper, opts ...gax.CallOption) error {
	for {
		if err := op.Poll(ctx, resp, opts...); err != nil {
			return err
		}
		if op.Done() {
			return nil
		}
		if err := sl(ctx, bo.Pause()); err != nil {
			return err
		}
	}
}

// Cancel starts asynchronous cancellation on a long-running operation. The server
// makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// status.Code(err) == codes.Unimplemented. Clients can use
// Poll or other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation,
// the operation is not deleted; instead, op.Poll returns an error
// with code Canceled.
func (op *Operation) Cancel(ctx context.Context, opts ...gax.CallOption) error {
	return op.c.CancelOperation(ctx, &pb.CancelOperationRequest{Name: op.Name()}, opts...)
}

// Delete deletes a long-running operation. This method indicates that the client is
// no longer interested in the operation result. It does not cancel the
// operation. If the server doesn't support this method, status.Code(err) == codes.Unimplemented.
func (op *Operation) Delete(ctx context.Context, opts ...gax.CallOption) error {
	return op.c.DeleteOperation(ctx, &pb.DeleteOperationRequest{Name: op.Name()}, opts...)
}
