//go:build js && wasm

package main

import (
	"encoding/json"
	"syscall/js"

	p "git.max-richter.dev/max/marka/parser"
	"git.max-richter.dev/max/marka/registry"
	"git.max-richter.dev/max/marka/template"
)

func wrapError(err error) string {
	errMap := map[string]any{"error": err.Error()}
	errJSON, _ := json.Marshal(errMap)
	return string(errJSON)
}

func MatchBlocks(this js.Value, args []js.Value) any {
	s := args[0].String()
	t := args[1].String()
	matched, err := p.MatchBlocks(s, t)
	if err != nil {
		return wrapError(err)
	}
	jsonString, _ := json.Marshal(matched)
	return string(jsonString)
}

func DetectType(this js.Value, args []js.Value) any {
	markdown := args[0].String()
	t, err := p.DetectType(markdown)
	if err != nil {
		return wrapError(err)
	}
	return t
}

func ParseFile(this js.Value, args []js.Value) any {
	markdown := args[0].String()
	res, err := p.ParseFile(markdown)
	if err != nil {
		return wrapError(err)
	}
	b, err := json.Marshal(res)
	if err != nil {
		return wrapError(err)
	}
	return string(b)
}

func ParseFileWithTemplate(this js.Value, args []js.Value) any {
	markdown := args[0].String()
	template := args[1].String()
	res, err := p.ParseFileWithTemplate(markdown, template)
	if err != nil {
		return wrapError(err)
	}
	b, err := json.Marshal(res)
	if err != nil {
		return wrapError(err)
	}
	return string(b)
}

func ListTemplates(this js.Value, args []js.Value) any {
	templates, err := registry.ListTemplates()
	if err != nil {
		return wrapError(err)
	}
	b, err := json.Marshal(templates)
	if err != nil {
		return wrapError(err)
	}
	return string(b)
}

func GetTemplate(this js.Value, args []js.Value) any {
	name := args[0].String()
	template, err := registry.GetTemplate(name)
	if err != nil {
		return wrapError(err)
	}
	return template
}

func CompileTemplate(this js.Value, args []js.Value) any {
	source := args[0].String()
	template, err := template.CompileTemplate(source)
	if err != nil {
		return wrapError(err)
	}
	b, err := json.Marshal(template)
	if err != nil {
		return wrapError(err)
	}
	return string(b)
}

func main() {
	marka := js.Global().Get("Object").New()

	marka.Set("matchBlocks", js.FuncOf(MatchBlocks))
	marka.Set("detectType", js.FuncOf(DetectType))
	marka.Set("parseFile", js.FuncOf(ParseFile))
	marka.Set("parseFileWithTemplate", js.FuncOf(ParseFileWithTemplate))
	marka.Set("listTemplates", js.FuncOf(ListTemplates))
	marka.Set("getTemplate", js.FuncOf(GetTemplate))
	marka.Set("compileTemplate", js.FuncOf(CompileTemplate))

	js.Global().Set("marka", marka)

	select {}
}