// Command server runs the go-wasm-web example on kjol's reusable wasmdevserver:
// it SSRs the app's static routes, hosts the /rsc server-component endpoint, and
// hot-swaps the wasm into the browser on change. It shows the coupling
// inversion — the framework (wasmdevserver) imports no app code; the app injects
// Build/Render/Document here.
//
// Run it from THIS directory (the relative paths below are resolved against it):
//
//	go run ./server            # from cmd/examples/go-wasm-web
package main

import (
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"kjol/vdom"
	"kjol/wasmdevserver"

	"gowasmweb/app"
)

func main() {
	addr := flag.String("addr", ":8085", "listen address")
	watch := flag.Bool("watch", true, "watch sources, rebuild wasm, hot-reload")
	flag.Parse()

	log.Fatal(wasmdevserver.Serve(wasmdevserver.Config{
		Addr:      *addr,
		Dir:       "./wwwroot",
		Watch:     *watch,
		WatchDirs: []string{"app", "wasm", "../../../vdom", "../../../wasmruntime", "../../../rsc"}, // example + kjol engine
		Build:     buildWasm,
		Render:    render,
		Document:  document,
	}))
}

// render SSRs a static route's #app inner HTML; ok=false ships an empty #app
// (client-rendered). It's the same neutral render the client runs, so the client
// hydrates it.
func render(path string) (string, bool) {
	if !app.StaticPaths[path] {
		return "", false
	}
	deps := app.Deps{Path: func() string { return path }} // Navigate is nil on the server
	return vdom.RenderHTML(app.Shell(deps, app.Routes(deps))), true
}

// document wraps the server-rendered inner HTML in the page shell. No whitespace
// between <div id="app"> and the markup, so hydration's childNodes line up. The
// dev server injects the livereload script before </body> in watch mode.
func document(inner string) string {
	return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>gowasm — a tiny Blazor-like engine</title>
<link rel="stylesheet" href="/bootstrap.min.css" />
</head>
<body>
<div id="app">` + inner + `</div>
<script src="/wasm_exec.js"></script>
<script src="/bootstrap.js"></script>
</body>
</html>`
}

// buildWasm runs the directive codegen (kjol/cmd/wasmgen), then compiles
// ./wasm to wwwroot/app.wasm. Returned combined output is shown in the browser
// overlay on failure.
func buildWasm() ([]byte, error) {
	if out, err := exec.Command("go", "run", "kjol/cmd/wasmgen", "./app").CombinedOutput(); err != nil {
		return out, err
	}
	cmd := exec.Command("go", "build", "-o", filepath.Join("wwwroot", "app.wasm"), "./wasm")
	cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm")
	return cmd.CombinedOutput()
}
