package gophertype

import (
	"html/template"
	"net/http"

	"git.kirsle.net/apps/gophertype/pkg/cache"
	"git.kirsle.net/apps/gophertype/pkg/console"
	"git.kirsle.net/apps/gophertype/pkg/controllers"
	"git.kirsle.net/apps/gophertype/pkg/models"
	"git.kirsle.net/apps/gophertype/pkg/responses"
	"git.kirsle.net/apps/gophertype/pkg/settings"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"github.com/urfave/negroni"
)

// Site is the master struct for the Gophertype server.
type Site struct {
	n   *negroni.Negroni
	mux *mux.Router
}

// NewSite initializes the Site.
func NewSite(pubroot string) *Site {
	// Initialize the settings.json inside the user root.
	if err := settings.SetFilename(pubroot); err != nil {
		panic(err)
	}

	site := &Site{}

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	n.Use(negroni.NewLogger())
	site.n = n

	// Register blog global template functions.
	responses.ExtraFuncs = template.FuncMap{
		"BlogIndex":         controllers.PartialBlogIndex,
		"RenderComments":    controllers.RenderComments,
		"RenderCommentsRO":  controllers.RenderCommentsRO,
		"RenderComment":     controllers.RenderComment,
		"RenderCommentForm": controllers.RenderCommentForm,
	}

	return site
}

// UseDB specifies the database to use.
func (s *Site) UseDB(driver string, path string) error {
	db, err := gorm.Open(driver, path)
	if err != nil {
		return err
	}

	console.Info("Using database driver '%s'", driver)
	models.UseDB(db)
	return nil
}

// SetupRedis connects to the Redis instance if available.
func (s *Site) SetupRedis() error {
	return cache.Connect()
}

// ListenAndServe starts the HTTP service.
func (s *Site) ListenAndServe(addr string) error {
	console.Info("Listening on %s", addr)
	return http.ListenAndServe(addr, s.n)
}
