package ginext

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

type WHandlerFunc func(PreContext) HTTPResponse

func Wrap(w *GinWrapper, fn WHandlerFunc) gin.HandlerFunc {

	return func(g *gin.Context) {

		reqctx := g.Request.Context()

		pctx := PreContext{
			wrapper:        w,
			ginCtx:         g,
			persistantData: &preContextData{},
		}

		for _, lstr := range w.listenerBeforeRequest {
			lstr(g)
		}

		wrap, stackTrace, panicObj := callPanicSafe(fn, pctx)
		if panicObj != nil {

			fmt.Printf("\n======== ======== STACKTRACE ======== ========\n%s\n======== ======== ======== ========\n\n", stackTrace)

			err := exerr.
				New(exerr.TypePanic, "Panic occured (in gin handler)").
				Any("panicObj", panicObj).
				Str("trace", stackTrace).
				Build()

			wrap = Error(err)
		}

		if g.Writer.Written() {
			panic("Writing in WrapperFunc is not supported")
		}

		if pctx.persistantData.sessionObj != nil {
			err := pctx.persistantData.sessionObj.Finish(reqctx, wrap)
			if err != nil {
				wrap = Error(exerr.Wrap(err, "Failed to finish session").Any("originalResponse", wrap).Build())
			}
		}

		for _, lstr := range w.listenerAfterRequest {
			lstr(g, wrap)
		}

		if reqctx.Err() == nil {
			wrap.Write(g)
		}
	}
}