package auth

import (
	"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
	"gitlab.thpeetz.de/kontor/kontor-go/pkg/properties"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2/bson"
)

var sessionDao = SessionDAO{Db: dao.KontorDb}

// EnsureLoggedIn ensures that a request will be aborted with an error
// if the user is not logged in
func EnsureLoggedIn() gin.HandlerFunc {
	return func(c *gin.Context) {
		// If there's an error or if the token is empty
		// the user is not logged in
		sessionInterface, _ := c.Get("session")
		sessionID := sessionInterface.(string)
		if session, err := sessionDao.GetSession(sessionID); err != nil || session.Username == "" {
			c.Redirect(http.StatusTemporaryRedirect, "/")
			//c.AbortWithStatus(http.StatusUnauthorized)
		}
	}
}

// EnsureAdminStatus ensures that a request will be aborted with an error
// if the user is not logged in
func EnsureAdminStatus() gin.HandlerFunc {
	return func(c *gin.Context) {
		// If there's an error or if the token is empty
		// the user is not logged in
		sessionInterface, _ := c.Get("session")
		sessionID := sessionInterface.(string)
		if session, err := sessionDao.GetSession(sessionID); err != nil || !session.IsAdmin {
			c.Redirect(http.StatusTemporaryRedirect, "/")
			//c.AbortWithStatus(http.StatusUnauthorized)
		}
	}
}

// EnsureNotLoggedIn ensures that a request will be aborted with an error
// if the user is already logged in
func EnsureNotLoggedIn() gin.HandlerFunc {
	return func(c *gin.Context) {
		// If there's no error or if the token is not empty
		// the user is already logged in
		sessionInterface, _ := c.Get("session")
		sessionID := sessionInterface.(string)
		if session, err := sessionDao.GetSession(sessionID); err != nil || session.Username != "" {
			c.Redirect(http.StatusTemporaryRedirect, "/")
			//c.AbortWithStatus(http.StatusUnauthorized)
		}
	}
}

// SetSessionStatus reads sessionId from cookie if available or create new session object
// and sets cookie accordingly.
func SetSessionStatus() gin.HandlerFunc {
	return func(c *gin.Context) {
		if sessionID, err := c.Cookie("session"); err == nil || sessionID != "" {
			c.Set("session", sessionID)
		} else {
			session, _ := sessionDao.GetSession(bson.NewObjectId().Hex())
			sessionID := session.ID.Hex()
			c.Set("session", sessionID)
			c.SetCookie("session", sessionID, 3600, "", "", false, true)
		}
	}
}

// SetSessionData populates session information with username, admin status of user and
// application version.
func SetSessionData(c *gin.Context, data gin.H) {
	sessionInterface, _ := c.Get("session")
	sessionID := sessionInterface.(string)
	session, _ := sessionDao.GetSession(sessionID)
	if gin.IsDebugging() {
		log.Printf("setSessionData(%v): %v", sessionID, session)
	}
	data["is_logged_in"] = (session.Username != "")
	data["is_admin"] = session.IsAdmin
	data["version"] = properties.Version
}
