// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package verror

import (
	"fmt"

	"v.io/v23/vdl"
)

func init() {
	// TODO(bprosnitz) Remove this old-style registration.
	// We must register the error conversion functions between vdl.WireError and
	// the standard error interface with the vdl package.  This allows the vdl
	// package to have minimal dependencies.
	vdl.RegisterNativeError(WireToNative, WireFromNative)

	// New-style error registration.
	vdl.RegisterNative(ErrorToNative, ErrorFromNative)
}

// TODO(toddw): rename Error{To,From}Native to Wire{To,From}Native, after we've
// switched to the new vdl Encoder/Decoder, and the old functions are no longer
// used.

// ErrorToNative converts from the wire to native representation of errors.
func ErrorToNative(wire *vdl.WireError, native *error) error {
	if wire == nil {
		*native = nil
		return nil
	}
	e := new(E)
	*native = e
	return WireToNative(*wire, e)
}

// ErrorFromNative converts from the native to wire representation of errors.
func ErrorFromNative(wire **vdl.WireError, native error) error {
	if native == nil {
		*wire = nil
		return nil
	}
	return WireFromNative(*wire, native)
}

// FromWire is a convenience for generated code to convert wire errors into
// native errors.
func FromWire(wire *vdl.WireError) error {
	var native error
	if err := ErrorToNative(wire, &native); err != nil {
		native = err
	}
	return native
}

// WireToNative converts from vdl.WireError to verror.E, which
// implements the standard go error interface.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireToNative(wire vdl.WireError, native *E) error {
	*native = E{
		ID:     ID(wire.Id),
		Action: retryToAction(wire.RetryCode),
		Msg:    wire.Msg,
	}
	for _, p := range wire.ParamList {
		var pNative interface{}
		if err := vdl.Convert(&pNative, p); err != nil {
			// It's questionable what to do if the conversion fails, or similarly if
			// the conversion ends up with a *vdl.Value, rather than a native Go
			// value.
			//
			// At the moment, for both cases we plug the *vdl.Value or conversion
			// error into the native params.  The idea is that this will still be more
			// useful to the user, since they'll still have the error Id and Action.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pNative = err
		}
		native.ParamList = append(native.ParamList, pNative)
	}
	return nil
}

// WireFromNative converts from the standard go error interface to
// verror.E, and then to vdl.WireError.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireFromNative(wire *vdl.WireError, native error) error {
	e := ExplicitConvert(ErrUnknown, "", "", "", native)
	*wire = vdl.WireError{
		Id:        string(ErrorID(e)),
		RetryCode: retryFromAction(Action(e)),
		Msg:       e.Error(),
	}
	for _, p := range params(e) {
		var pWire *vdl.Value
		if err := vdl.Convert(&pWire, p); err != nil {
			// It's questionable what to do here if the conversion fails, similarly to
			// the conversion failure above in WireToNative.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pWire = vdl.StringValue(nil, err.Error())
		}
		wire.ParamList = append(wire.ParamList, pWire)
	}
	return nil
}

func retryToAction(retry vdl.WireRetryCode) ActionCode {
	switch retry {
	case vdl.WireRetryCodeNoRetry:
		return NoRetry
	case vdl.WireRetryCodeRetryConnection:
		return RetryConnection
	case vdl.WireRetryCodeRetryRefetch:
		return RetryRefetch
	case vdl.WireRetryCodeRetryBackoff:
		return RetryBackoff
	}
	// Backoff to no retry by default.
	return NoRetry
}

func retryFromAction(action ActionCode) vdl.WireRetryCode {
	switch action.RetryAction() {
	case NoRetry:
		return vdl.WireRetryCodeNoRetry
	case RetryConnection:
		return vdl.WireRetryCodeRetryConnection
	case RetryRefetch:
		return vdl.WireRetryCodeRetryRefetch
	case RetryBackoff:
		return vdl.WireRetryCodeRetryBackoff
	}
	// Backoff to no retry by default.
	return vdl.WireRetryCodeNoRetry
}

// VDLRead implements the logic to read x from dec.
//
// Unlike regular VDLRead implementations, this handles the case where the
// decoder contains a nil value, to make code generation simpler.
func VDLRead(dec vdl.Decoder, x *error) error {
	if err := dec.StartValue(); err != nil {
		return err
	}
	if dec.IsNil() {
		if (dec.StackDepth() == 1 || dec.IsAny()) && !vdl.Compatible(vdl.ErrorType, dec.Type()) {
			return fmt.Errorf("incompatible error, from %v", dec.Type())
		}
		*x = nil
		return dec.FinishValue()
	}
	dec.IgnoreNextStartValue()
	var wire vdl.WireError
	if err := wire.VDLRead(dec); err != nil {
		return err
	}
	nativePtr := new(E)
	if err := WireToNative(wire, nativePtr); err != nil {
		return err
	}
	*x = nativePtr
	return nil
}

// VDLWrite implements the logic to write x to enc.
//
// Unlike regular VDLWrite implementations, this handles the case where x
// contains a nil value, to make code generation simpler.
func VDLWrite(enc vdl.Encoder, x error) error {
	if x == nil {
		return enc.NilValue(vdl.ErrorType)
	}
	var wire vdl.WireError
	if err := WireFromNative(&wire, x); err != nil {
		return err
	}
	return wire.VDLWrite(enc)
}
