package errors

import (
	"fmt"

	pkg_errors "github.com/pkg/errors"
)

//extends default golang error interface
type ErrorWithCause interface {
	error
	Cause() error
	Code() int
}

type ErrorWithIs interface {
	error
	Is(specificError error) bool
}

func New(message string) error {
	err := &CustomError{
		message: message,
		caller:  GetCaller(2),
		cause:   nil,
	}
	return err
}

func Error(message string) error {
	err := &CustomError{
		message: message,
		caller:  GetCaller(2),
		cause:   nil,
	}
	return err
}

func Errorf(format string, args ...interface{}) error {
	err := &CustomError{
		message: fmt.Sprintf(format, args...),
		caller:  GetCaller(2),
		cause:   nil,
	}
	return err
}

func Wrapf(err error, format string, args ...interface{}) error {
	if err == nil {
		return nil
	}

	wrappedErr := &CustomError{
		message: fmt.Sprintf(format, args...),
		caller:  GetCaller(2),
		cause:   err,
	}

	return wrappedErr
}

func Wrap(err error, msg string) error {
	if err == nil {
		return nil
	}

	wrappedErr := &CustomError{
		message: msg,
		caller:  GetCaller(2),
		cause:   err,
	}

	return wrappedErr
}

func HTTP(code int, err error, format string, args ...interface{}) error {
	wrappedErr := &CustomError{
		code:    code,
		message: fmt.Sprintf(format, args...),
		caller:  GetCaller(2),
		cause:   err,
	}

	return wrappedErr
}

func HTTPWithMsg(code int, format string, args ...interface{}) error {
	errorString := fmt.Sprintf(format, args...)

	wrappedErr := &CustomError{
		code:    code,
		message: errorString,
		caller:  GetCaller(2),
		cause:   Error(errorString),
	}

	return wrappedErr
}

func HTTPCodeOnly(code int) error {
	return HTTP(code, nil, "")
}

func HTTPWithError(code int, err error) error {
	wrappedErr := &CustomError{
		code:    code,
		message: err.Error(),
		caller:  GetCaller(2),
		cause:   err,
	}

	return wrappedErr
}

type Description struct {
	Message string       `json:"error"`
	Source  *CallerInfo  `json:"source,omitempty"`
	Cause   *Description `json:"cause,omitempty"`
}

//from github.com/pkg/errors:
type stackTracer interface {
	StackTrace() pkg_errors.StackTrace
}