package metrics

// ErrUnknownCode is a string code representing an unknown error
// This will be used when no error code is sent by the handler
const ErrUnknownCode = "PIT-000"

// Error is an error with a code, message and metadata
type Error struct {
	Code     string
	Message  string
	Metadata map[string]string
}

//NewError ctor
func NewError(err error, code string, metadata ...map[string]string) *Error {
	if pitayaErr, ok := err.(*Error); ok {
		if len(metadata) > 0 {
			mergeMetadatas(pitayaErr, metadata[0])
		}
		return pitayaErr
	}

	e := &Error{
		Code:    code,
		Message: err.Error(),
	}
	if len(metadata) > 0 {
		e.Metadata = metadata[0]
	}
	return e

}

func (e *Error) Error() string {
	return e.Message
}

func mergeMetadatas(pitayaErr *Error, metadata map[string]string) {
	if pitayaErr.Metadata == nil {
		pitayaErr.Metadata = metadata
		return
	}

	for key, value := range metadata {
		pitayaErr.Metadata[key] = value
	}
}

// CodeFromError returns the code of error.
// If error is nil, return empty string.
// If error is not a pitaya error, returns unkown code
func CodeFromError(err error) string {
	if err == nil {
		return ""
	}

	pitayaErr, ok := err.(*Error)
	if !ok {
		return ErrUnknownCode
	}

	if pitayaErr == nil {
		return ""
	}

	return pitayaErr.Code
}
