package util

import (
	"net/http"
	"path"

	"bytes"
	"io"
	"path/filepath"

	"amuz.es/go/mnemonics/bind/template"
	"github.com/flosch/pongo2"
	"github.com/gin-gonic/gin/render"
)

type (
	PongoRelease struct {
		templateSet *pongo2.TemplateSet
		Path        string
	}

	PongoDebug struct {
		Path string
	}

	Pongo struct {
		Template *pongo2.Template
		Name     string
		Data     interface{}
	}

	Context pongo2.Context
)

func TemplateSourceRelease(path string) *PongoRelease {
	ts := pongo2.NewSet(path, &memoryTemplateLoader{loaderFunc: template.Asset})
	return &PongoRelease{ts, path}
}

func (p PongoRelease) Instance(name string, data interface{}) render.Render {
	t := pongo2.Must(p.templateSet.FromFile(path.Join(p.Path, name)))

	return Pongo{
		Template: t,
		Name:     name,
		Data:     data,
	}
}
func TemplateSourceDebug(path string) *PongoDebug {
	return &PongoDebug{path}
}

func (p PongoDebug) Instance(name string, data interface{}) render.Render {

	t := pongo2.Must(pongo2.FromFile(path.Join(p.Path, name)))
	return Pongo{
		Template: t,
		Name:     name,
		Data:     data,
	}
}

func (p Pongo) Render(w http.ResponseWriter) error {
	ctx := pongo2.Context(p.Data.(Context))
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	return p.Template.ExecuteWriter(ctx, w)
}

type memoryTemplateLoader struct {
	loaderFunc     func(path string) ([]byte, error)
	fallbackLoader *pongo2.TemplateLoader
}

func (m memoryTemplateLoader) Abs(base, name string) string {
	if filepath.IsAbs(name) || base == "" {
		return name
	}

	if name == "" {
		return base
	}

	return filepath.Dir(base) + string(filepath.Separator) + name
}

func (m memoryTemplateLoader) Get(path string) (io.Reader, error) {
	data, err := m.loaderFunc(filepath.Clean(path))
	if err != nil {
		if m.fallbackLoader != nil {
			return (*m.fallbackLoader).Get(path)
		}

		return nil, err
	}

	return bytes.NewReader(data), nil
}
