// Package webpublic contains the public webserver
// which provides the primary and only intended access point
// for interacting with the system.
//
// # Sections
//
// - Frontend: Serves the various web frontend versions
//   - Main: The original Linstrom specific frontend
//   - NoJs: An entirely serverside rendered frontend, no JS included
//   - Custom: Custom frontend files will be served here
//
// - API: Endpoints for the actual interactions
//   - Frontend: The API used by the main frontend
//   - Masto: Mastodon compatible adapter for internal structures
//   - ActivityPub: For integration with the Fediverse via ActivityPub
//   - Linstrom-RPC: For Linstrom to Linstrom server communication
//
// # Guarantees
//
//   - The Masto and ActivityPub API will remain stable
//   - Frontend API might change, but the intended consumer (Main frontend)
//     will always be up to date with the changes
//   - Linstrom-RPC API is versioned and will keep
//     a few versions of backwards compatibility
//
// TODO: Decide how long the Linstrom-RPC API will remain backwards compatible
package webpublic

import (
	"context"
	"fmt"
	"net/http"

	webutils "git.mstar.dev/mstar/goutils/http"

	"git.mstar.dev/mstar/linstrom/web/public/api"
)

type Server struct {
	server *http.Server
}

func New(addr string, duckImg *string) *Server {
	handler := http.NewServeMux()
	handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(500)
		fmt.Fprint(w, "not implemented")
	})
	handler.Handle("/api/", http.StripPrefix("/api", api.BuildApiRouter()))
	handler.HandleFunc("GET /.well-known/webfinger", api.WellKnownWebfinger)
	handler.HandleFunc("GET /.well-known/nodeinfo", api.WellKnownNodeinfo)
	handler.HandleFunc("GET /nodeinfo/2.1", api.Nodeinfo)
	handler.HandleFunc("GET /errors/{name}", errorTypeHandler)
	handler.HandleFunc("GET /default-image", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add("Content-Type", "image/web")
		w.Header().Add("Content-Disposition", "attachment; filename=\"duck.webp\"")
		fmt.Fprint(w, *duckImg)
	})
	server := http.Server{
		Handler: webutils.ChainMiddlewares(
			handler,
			webutils.BuildLoggingMiddleware(map[string]string{"server": "public"}),
		),
		Addr: addr,
	}
	return &Server{&server}
}

func (s *Server) Start() error {
	return s.server.ListenAndServe()
}

func (s *Server) Stop() error {
	return s.server.Shutdown(context.Background())
}
