package main

import (
	"context"
	"log"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"github.com/gin-gonic/gin"

	"srs.epita.fr/fic-server/admin/api"
	"srs.epita.fr/fic-server/settings"
)

type App struct {
	router *gin.Engine
	srv    *http.Server
	cfg    *settings.Settings
	bind   string
}

func NewApp(cfg *settings.Settings, baseURL string, bind string) App {
	if !cfg.WorkInProgress {
		gin.SetMode(gin.ReleaseMode)
	}
	gin.ForceConsoleColor()
	router := gin.Default()

	api.DeclareRoutes(router.Group(""))

	var baserouter *gin.RouterGroup
	if len(baseURL) > 0 {
		router.GET("/", func(c *gin.Context) {
			c.Redirect(http.StatusFound, baseURL)
		})
		router.GET(filepath.Dir(baseURL)+"/files/*_", func(c *gin.Context) {
			path := c.Request.URL.Path
			c.Redirect(http.StatusFound, filepath.Join(baseURL, strings.TrimPrefix(path, filepath.Dir(baseURL))))
		})

		baserouter = router.Group(baseURL)

		api.DeclareRoutes(baserouter)
		declareStaticRoutes(baserouter, cfg, baseURL)
	} else {
		declareStaticRoutes(router.Group(""), cfg, "")
	}

	app := App{
		router: router,
		bind:   bind,
	}

	return app
}

func (app *App) Start() {
	app.srv = &http.Server{
		Addr:              app.bind,
		Handler:           app.router,
		ReadHeaderTimeout: 15 * time.Second,
		ReadTimeout:       15 * time.Second,
		WriteTimeout:      10 * time.Second,
		IdleTimeout:       30 * time.Second,
	}

	log.Printf("Ready, listening on %s\n", app.bind)
	if err := app.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		log.Fatalf("listen: %s\n", err)
	}
}

func (app *App) Stop() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := app.srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
}
