// Copyright 2016 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 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 (
	"errors"
	"fmt"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	gax "github.com/googleapis/gax-go"

	"golang.org/x/net/context"

	pb "google.golang.org/genproto/googleapis/longrunning"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

// 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     pb.OperationsClient
	proto *pb.Operation
}

// 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(conn *grpc.ClientConn, proto *pb.Operation) *Operation {
	return &Operation{
		c:     pb.NewOperationsClient(conn),
		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 proto.Message) error {
	if m := op.proto.Metadata; m != nil {
		return ptypes.UnmarshalAny(m, meta)
	}
	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 proto.Message) error {
	if !op.Done() {
		p, err := op.c.GetOperation(ctx, &pb.GetOperationRequest{Name: op.Name()})
		if err != nil {
			return err
		}
		op.proto = p
	}
	if !op.Done() {
		return nil
	}

	switch r := op.proto.Result.(type) {
	case *pb.Operation_Error:
		// TODO (pongad): r.Details may contain further information
		return grpc.Errorf(codes.Code(r.Error.Code), "%s", r.Error.Message)
	case *pb.Operation_Response:
		if resp == nil {
			return nil
		}
		return ptypes.UnmarshalAny(r.Response, resp)
	default:
		return fmt.Errorf("unsupported result type %[1]T: %[1]v", r)
	}
}

// Wait blocks until the operation is completed.
// If resp != nil, Wait stores the response in resp.
//
// See documentation of Poll for error-handling information.
func (op *Operation) Wait(ctx context.Context, resp proto.Message) error {
	bo := gax.Backoff{
		Initial: 100 * time.Millisecond,
		Max:     10 * time.Second,
	}
	return op.wait(ctx, resp, &bo, gax.Sleep)
}

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 proto.Message, bo *gax.Backoff, sl sleeper) error {
	for {
		if err := op.Poll(ctx, resp); 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
// grpc.Code(error) == 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) error {
	_, err := op.c.CancelOperation(ctx, &pb.CancelOperationRequest{Name: op.Name()})
	return err
}

// 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, grpc.Code(error) == codes.Unimplemented.
func (op *Operation) Delete(ctx context.Context) error {
	_, err := op.c.DeleteOperation(ctx, &pb.DeleteOperationRequest{Name: op.Name()})
	return err
}
