package main

import (
	"context"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

type App struct {
	router *gin.Engine
	srv    *http.Server
	bind   string
	ips    []string
}

func NewApp(htpasswd_file *string, restrict_to_ips *string, baseURL string, bind string) App {
	gin.ForceConsoleColor()
	router := gin.Default()

	var baserouter *gin.RouterGroup
	if len(baseURL) > 1 {
		router.GET("/", func(c *gin.Context) {
			c.Redirect(http.StatusFound, baseURL)
		})

		baserouter = router.Group(baseURL)
	} else {
		baserouter = router.Group("")
	}

	if htpasswd_file != nil && len(*htpasswd_file) > 0 {
		baserouter.Use(Htpassword(*htpasswd_file))
	}

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

	if restrict_to_ips != nil && len(*restrict_to_ips) > 0 {
		app.loadAndWatchIPs(*restrict_to_ips)
		baserouter.Use(app.Restrict2IPs)
	}

	declareStaticRoutes(baserouter, baseURL)

	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)
	}
}
