package responses

import (
	"fmt"
	"html/template"
	"net/http"

	"git.kirsle.net/apps/gophertype/pkg/constants"
	"git.kirsle.net/apps/gophertype/pkg/session"
)

// ExtraFuncs lets the core app inject extra template functions for all templates.
// Use cases include inserting comment or blog partials on other pages.
var ExtraFuncs template.FuncMap

// TemplateFuncs available to all templates.
func TemplateFuncs(r *http.Request) template.FuncMap {
	funcs := template.FuncMap{
		"CSRF":         CSRF(r),
		"CSRFToken":    CSRFToken(r),
		"FormValue":    FormValue(r),
		"TestFunction": TestFunction(r),
	}
	for k, v := range ExtraFuncs {
		funcs[k] = v
	}
	return funcs
}

// CSRF returns the current CSRF token as an HTML hidden form field.
func CSRF(r *http.Request) func() template.HTML {
	return func() template.HTML {
		ctx := r.Context()
		if token, ok := ctx.Value(session.CSRFKey).(string); ok {
			return template.HTML(fmt.Sprintf(
				`<input type="hidden" name="%s" value="%s">`,
				constants.CSRFFormName,
				token,
			))
		}
		return template.HTML("[error: csrf token not found in request context]")
	}
}

// CSRFToken returns the current CSRF token as a string.
func CSRFToken(r *http.Request) func() template.HTML {
	return func() template.HTML {
		ctx := r.Context()
		if token, ok := ctx.Value(session.CSRFKey).(string); ok {
			return template.HTML(token)
		}
		return template.HTML("[error: csrf token not found in request context]")
	}
}

// FormValue returns a form value (1st item only).
func FormValue(r *http.Request) func(string) string {
	return func(key string) string {
		return r.FormValue(key)
	}
}

// TestFunction is a "hello world" template function.
func TestFunction(r *http.Request) func() template.HTML {
	return func() template.HTML {
		return template.HTML("TestFunction() called")
	}
}
