/*
Copyright 2017 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 spanner

import (
	"context"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	edpb "google.golang.org/genproto/googleapis/rpc/errdetails"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
)

const (
	retryInfoKey = "google.rpc.retryinfo-bin"
)

// isErrorClosing reports whether the error is generated by gRPC layer talking
// to a closed server.
func isErrorClosing(err error) bool {
	if err == nil {
		return false
	}
	if ErrCode(err) == codes.Internal && strings.Contains(ErrDesc(err), "transport is closing") {
		// Handle the case when connection is closed unexpectedly.
		// TODO: once gRPC is able to categorize this as retryable error, we
		//  should stop parsing the error message here.
		return true
	}
	return false
}

// isErrorRST reports whether the error is generated by gRPC client receiving a
// RST frame from server.
func isErrorRST(err error) bool {
	if err == nil {
		return false
	}
	if ErrCode(err) == codes.Internal && strings.Contains(ErrDesc(err), "stream terminated by RST_STREAM") {
		// TODO: once gRPC is able to categorize this error as "go away" or "retryable",
		// we should stop parsing the error message.
		return true
	}
	return false
}

// isErrorUnexpectedEOF returns true if error is generated by gRPC layer
// receiving io.EOF unexpectedly.
func isErrorUnexpectedEOF(err error) bool {
	if err == nil {
		return false
	}
	// Unexpected EOF is a transport layer issue that could be recovered by
	// retries. The most likely scenario is a flaky RecvMsg() call due to
	// network issues.
	//
	// For grpc version >= 1.14.0, the error code is Internal.
	// (https://github.com/grpc/grpc-go/releases/tag/v1.14.0)
	if ErrCode(err) == codes.Internal && strings.Contains(ErrDesc(err), "unexpected EOF") {
		return true
	}
	// For grpc version < 1.14.0, the error code in Unknown.
	if ErrCode(err) == codes.Unknown && strings.Contains(ErrDesc(err), "unexpected EOF") {
		return true
	}
	return false
}

// isErrorUnavailable returns true if the error is about server being
// unavailable.
func isErrorUnavailable(err error) bool {
	if err == nil {
		return false
	}
	if ErrCode(err) == codes.Unavailable {
		return true
	}
	return false
}

// isRetryable returns true if the Cloud Spanner error being checked is a
// retryable error.
func isRetryable(err error) bool {
	if isErrorClosing(err) {
		return true
	}
	if isErrorUnexpectedEOF(err) {
		return true
	}
	if isErrorRST(err) {
		return true
	}
	if isErrorUnavailable(err) {
		return true
	}
	return false
}

// errContextCanceled returns *spanner.Error for canceled context.
func errContextCanceled(ctx context.Context, lastErr error) error {
	if ctx.Err() == context.DeadlineExceeded {
		return spannerErrorf(codes.DeadlineExceeded, "%v, lastErr is <%v>", ctx.Err(), lastErr)
	}
	return spannerErrorf(codes.Canceled, "%v, lastErr is <%v>", ctx.Err(), lastErr)
}

// extractRetryDelay extracts retry backoff if present.
func extractRetryDelay(err error) (time.Duration, bool) {
	trailers := errTrailers(err)
	if trailers == nil {
		return 0, false
	}
	elem, ok := trailers[retryInfoKey]
	if !ok || len(elem) <= 0 {
		return 0, false
	}
	_, b, err := metadata.DecodeKeyValue(retryInfoKey, elem[0])
	if err != nil {
		return 0, false
	}
	var retryInfo edpb.RetryInfo
	if proto.Unmarshal([]byte(b), &retryInfo) != nil {
		return 0, false
	}
	delay, err := ptypes.Duration(retryInfo.RetryDelay)
	if err != nil {
		return 0, false
	}
	return delay, true
}
