package templates

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

	"git.kirsle.net/apps/gosocial/pkg/config"
	"git.kirsle.net/apps/gosocial/pkg/markdown"
	"git.kirsle.net/apps/gosocial/pkg/photo"
	"git.kirsle.net/apps/gosocial/pkg/session"
	"git.kirsle.net/apps/gosocial/pkg/utility"
)

// TemplateFuncs available to all pages.
func TemplateFuncs(r *http.Request) template.FuncMap {
	return template.FuncMap{
		"InputCSRF":         InputCSRF(r),
		"SincePrettyCoarse": SincePrettyCoarse(),
		"ComputeAge":        utility.Age,
		"Split":             strings.Split,
		"ToMarkdown":        ToMarkdown,
		"PhotoURL":          photo.URLPath,
		"Now":               time.Now,
		"PrettyTitle": func() template.HTML {
			return template.HTML(fmt.Sprintf(
				`<strong style="color: #0077FF">non</strong>` +
					`<strong style="color: #FF77FF">shy</strong>`,
			))
		},
		"Pluralize64": func(count int64, labels ...string) string {
			if len(labels) < 2 {
				labels = []string{"", "s"}
			}

			if count == 1 {
				return labels[0]
			} else {
				return labels[1]
			}
		},
		"Pluralize": func(count int, labels ...string) string {
			if len(labels) < 2 {
				labels = []string{"", "s"}
			}

			if count == 1 {
				return labels[0]
			} else {
				return labels[1]
			}
		},
		"Substring": func(value string, n int) string {
			if n > len(value) {
				return value
			}
			return value[:n]
		},
		"IterRange": func(start, n int) []int {
			var result = []int{}
			for i := start; i <= n; i++ {
				result = append(result, i)
			}
			return result
		},
		"SubtractInt": func(a, b int) int {
			return a - b
		},
	}
}

// InputCSRF returns the HTML snippet for a CSRF token hidden input field.
func InputCSRF(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">`,
				config.CSRFInputName,
				token,
			))
		} else {
			return template.HTML(`[CSRF middleware error]`)
		}
	}
}

// SincePrettyCoarse formats a time.Duration in plain English. Intended for "joined 2 months ago" type
// strings - returns the coarsest level of granularity.
func SincePrettyCoarse() func(time.Time) template.HTML {
	return func(since time.Time) template.HTML {
		return template.HTML(utility.FormatDurationCoarse(time.Since(since)))
	}
}

// ToMarkdown renders input text as Markdown.
func ToMarkdown(input string) template.HTML {
	return template.HTML(markdown.Render(input))
}
