package core

import "fmt"

type ErrorCode int

const (
	EGeneralError ErrorCode = iota + 1
	EInternalError
	EMethodNotImplemented
	EResourceNotFound
	ENotAvailable
	EParentFail
)

type Error struct {
	Code   ErrorCode
	msg    string
	Source error
}

func (e Error) Error() string {
	s := fmt.Sprintf("%s, Code: %d", e.msg, e.Code)
	if e.Source == nil {
		return s
	}
	return s + fmt.Sprintf(", caused by %T:%s", e.Source, e.Source)
}

var NotImplementedError = Error{msg: "not implemented", Code: EMethodNotImplemented}

func NewInternalError(msg string, err ...error) Error {
	e := Error{msg: msg, Code: EInternalError}
	if len(err) > 0 {
		e.Source = err[0]
	}
	return e
}

func NewNotAvailableError(err ...error) Error {
	e := Error{msg: "not available", Code: ENotAvailable}
	if len(err) > 0 {
		e.Source = err[0]
	}
	return e
}

func NewParentFailError(at string, err error) Error {
	return Error{msg: "parent fail at " + at, Code: EParentFail, Source: err}
}

var NotFound = Error{msg: "not found", Code: EResourceNotFound}
