package ginext

import (
	"context"
	"github.com/gin-gonic/gin"
	"gogs.mikescher.com/BlackForestBytes/goext/exerr"
	"gogs.mikescher.com/BlackForestBytes/goext/langext"
)

type jsonAPIErrResponse struct {
	err     *exerr.ExErr
	headers []headerval
	cookies []cookieval
}

func (j jsonAPIErrResponse) Error() error {
	return j.err
}

func (j jsonAPIErrResponse) Write(g *gin.Context) {
	for _, v := range j.headers {
		g.Header(v.Key, v.Val)
	}
	for _, v := range j.cookies {
		g.SetCookie(v.name, v.value, v.maxAge, v.path, v.domain, v.secure, v.httpOnly)
	}

	exerr.Get(j.err).Output(context.Background(), g)

	j.err.CallListener(exerr.MethodOutput)
}

func (j jsonAPIErrResponse) WithHeader(k string, v string) HTTPResponse {
	j.headers = append(j.headers, headerval{k, v})
	return j
}

func (j jsonAPIErrResponse) WithCookie(name string, value string, maxAge int, path string, domain string, secure bool, httpOnly bool) HTTPResponse {
	j.cookies = append(j.cookies, cookieval{name, value, maxAge, path, domain, secure, httpOnly})
	return j
}

func (j jsonAPIErrResponse) IsSuccess() bool {
	return false
}

func (j jsonAPIErrResponse) Statuscode() int {
	return langext.Coalesce(j.err.RecursiveStatuscode(), 0)
}

func (j jsonAPIErrResponse) BodyString(*gin.Context) *string {
	if str, err := j.err.ToDefaultAPIJson(); err == nil {
		return &str
	} else {
		return nil
	}
}

func (j jsonAPIErrResponse) ContentType() string {
	return "application/json"
}

func (j jsonAPIErrResponse) Headers() []string {
	return langext.ArrMap(j.headers, func(v headerval) string { return v.Key + "=" + v.Val })
}

func (j jsonAPIErrResponse) Unwrap() error {
	return j.err
}

func Error(e error) HTTPResponse {
	return &jsonAPIErrResponse{
		err: exerr.FromError(e),
	}
}

func ErrWrap(e error, errorType exerr.ErrorType, msg string) HTTPResponse {
	return &jsonAPIErrResponse{
		err: exerr.FromError(exerr.Wrap(e, msg).WithType(errorType).Build()),
	}
}