/*
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 (
	"fmt"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
)

// Error is the structured error returned by Cloud Spanner client.
type Error struct {
	// Code is the canonical error code for describing the nature of a
	// particular error.
	Code codes.Code
	// Desc explains more details of the error.
	Desc string
	// trailers are the trailers returned in the response, if any.
	trailers metadata.MD
}

// Error implements error.Error.
func (e *Error) Error() string {
	if e == nil {
		return fmt.Sprintf("spanner: OK")
	}
	return fmt.Sprintf("spanner: code = %q, desc = %q", e.Code, e.Desc)
}

// decorate decorates an existing spanner.Error with more information.
func (e *Error) decorate(info string) {
	e.Desc = fmt.Sprintf("%v, %v", info, e.Desc)
}

// spannerErrorf generates a *spanner.Error with the given error code and
// description.
func spannerErrorf(ec codes.Code, format string, args ...interface{}) error {
	return &Error{
		Code: ec,
		Desc: fmt.Sprintf(format, args...),
	}
}

// toSpannerError converts general Go error to *spanner.Error.
func toSpannerError(err error) error {
	return toSpannerErrorWithMetadata(err, nil)
}

// toSpannerErrorWithMetadata converts general Go error and grpc trailers to *spanner.Error.
// Note: modifies original error if trailers aren't nil
func toSpannerErrorWithMetadata(err error, trailers metadata.MD) error {
	if err == nil {
		return nil
	}
	if se, ok := err.(*Error); ok {
		if trailers != nil {
			se.trailers = metadata.Join(se.trailers, trailers)
		}
		return se
	}
	switch {
	case err == context.DeadlineExceeded:
		return &Error{codes.DeadlineExceeded, err.Error(), trailers}
	case err == context.Canceled:
		return &Error{codes.Canceled, err.Error(), trailers}
	case grpc.Code(err) == codes.Unknown:
		return &Error{codes.Unknown, err.Error(), trailers}
	default:
		return &Error{grpc.Code(err), grpc.ErrorDesc(err), trailers}
	}
}

// ErrCode extracts the canonical error code from a Go error.
func ErrCode(err error) codes.Code {
	se, ok := toSpannerError(err).(*Error)
	if !ok {
		return codes.Unknown
	}
	return se.Code
}

// ErrDesc extracts the Cloud Spanner error description from a Go error.
func ErrDesc(err error) string {
	se, ok := toSpannerError(err).(*Error)
	if !ok {
		return err.Error()
	}
	return se.Desc
}

// errTrailers extracts the grpc trailers if present from a Go error.
func errTrailers(err error) metadata.MD {
	se, ok := err.(*Error)
	if !ok {
		return nil
	}
	return se.trailers
}
