package service

import (
	"net/http"

	"github.com/go-chi/chi"
	chimiddleware "github.com/go-chi/chi/middleware"
	"go.uber.org/zap"
	"git.ssns.se/git/frozendragon/minecraft-ui/internal/config"
	"git.ssns.se/git/frozendragon/minecraft-ui/internal/rest"
	"git.ssns.se/git/frozendragon/minecraft-ui/internal/server"
	"context"
	"git.ssns.se/git/frozendragon/minecraft-ui/internal/resource/minecraft-log"
	"strings"
	"git.ssns.se/git/frozendragon/minecraft-ui/internal/resource/minecraft-status"
)

// Service defines the service instance.
type Service struct {
	logger *zap.Logger
	server *server.Server
}

// New instantiates a new service instance.
func New(conf *config.Config) (*Service, error) {
	logResource := minecraft_log.Resource{
		Logger: conf.Logger,
	}
	statusResource := minecraft_status.Resource{
		Logger: conf.Logger,
	}

	// Routes

	r := chi.NewRouter()

	//r.Get("/robots.txt", router.ServeRobots)

	// Simple Authenticated routes
	r.Group(func(r chi.Router) {
		r.Handle("/logger", conf.LoggerConfig.Level)
	})

	FileServer(r, "/ui", http.Dir("etc/static"))

	// API routes
	r.Route("/", func(r chi.Router) {
		//r.Use(middleware.SimpleBasicAuth(conf.BasicAuthUser, conf.BasicAuthPass))
		r.Use(chimiddleware.StripSlashes)

		r.Get("/minecraft-log", logResource.Get)
		r.Get("/minecraft-status", statusResource.Get)
		r.Post("/minecraft-status", statusResource.Post)
	})

	h := chi.ServerBaseContext(context.Background(), r)
	s := server.New(conf.Addr, h, server.WithErrorLog(conf.StdLogger))

	return &Service{
		logger: conf.Logger,
		server: s,
	}, nil
}

// Start starts the service.
func (s *Service) Start() error {
	return s.server.Start()
}

// Stop stops the service.
func (s *Service) Stop() error {
	return s.server.Stop()
}

// rootHandler is the root handler for request to `/`.
func rootHandler(w http.ResponseWriter, req *http.Request) {
	rest.JSON(w, req, struct{}{})
}

func FileServer(r chi.Router, path string, root http.FileSystem) {
	if strings.ContainsAny(path, "{}*") {
		panic("router: FileServer does not permit URL parameters.")
	}

	fs := http.StripPrefix(path, http.FileServer(root))

	if path != "/" && !strings.HasSuffix(path, "/") {
		r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP)
		path += "/"
	}
	path += "*"

	r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fs.ServeHTTP(w, r)
	}))
}