package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
)

func HttpAuth() gin.HandlerFunc {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	return func(c *gin.Context) {
		// Search signed-in userID
		userID := 0
		if userID == 0 {
			// Return 404 and abort handlers chain.
			c.String(http.StatusNotFound, "404 page not found")
			c.AbortWithStatus(http.StatusNotFound)
		}
	}
}

func HttpNoAuth() gin.HandlerFunc {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	return func(c *gin.Context) {
	}
}

func HttpPostSubmit(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	t, err := GetCSRFToken(c)

	if err != nil {
		c.String(http.StatusBadRequest, "bad token")
		return
	}

	if !t.Valid() {
		c.String(http.StatusBadRequest, "expired token")
		return
	}

	switch t.GetPath() {
	case "signin":
		log.WithFields(log.Fields{"call": "Context.Request.ParseForm", "err": err}).Debugf("submit signin")
		HttpSubmitSignIn(c)
		HttpAnyIndex(c)
	default:
		log.WithFields(log.Fields{"call": "Context.Request.ParseForm", "err": err}).Debugf("submit %s", t.GetPath())
		c.String(http.StatusBadRequest, "")
	}

	if GetWebSessionUserID(c) > 0 {
		c.Redirect(http.StatusTemporaryRedirect, "/p/home")
	} else {
		SetCSRFToken(c)
		warning, _ := c.Cookie("warning")
		c.SetCookie("warning", "", -1, "/", cfg.Admin.Addr, false, true)
		c.HTML(http.StatusOK, "page-signin.html", gin.H{
			"Error": warning,
		})
	}
}

func HttpGetRecover(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	SetCSRFToken(c)
	c.HTML(http.StatusOK, "page-recover.html", gin.H{})
}

func HttpGetSignIn(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	SetCSRFToken(c)
	c.HTML(http.StatusOK, "page-signin.html", gin.H{})
}

func HttpAnyIndex(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	if GetWebSessionUserID(c) > 0 {
		c.Redirect(http.StatusTemporaryRedirect, "/p/home")
	} else {
		c.Redirect(http.StatusTemporaryRedirect, "/u/signin")
	}
}

func HttpAnyHome(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	if GetWebSessionUserID(c) == 0 {
		c.Redirect(http.StatusTemporaryRedirect, "/u/signin")
	} else {
		SetCSRFToken(c)
		c.HTML(http.StatusOK, "page-home.html", gin.H{})
	}
}

func GetWebSessionUserID(c *gin.Context) uint64 {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	return 0
}

func HttpSubmitSignIn(c *gin.Context) {
	log.WithFields(log.Fields{}).Debugf("starting")
	defer log.WithFields(log.Fields{}).Debugf("done")

	err := c.Request.ParseForm()
	if err != nil {
		c.SetCookie("warning", "Unable to parse form", 0, "/", cfg.Admin.URL, false, true)
		log.WithFields(log.Fields{"call": "Context.Request.ParseForm", "err": err}).Debugf("")
		return
	}

	username := c.Request.FormValue("username")
	password := c.Request.FormValue("password")

	userID, err := FindUserID(username)
	if err != nil {
		c.SetCookie("warning", "Invalid user or password", 0, "/", cfg.Admin.URL, false, true)
		log.WithFields(log.Fields{"call": "FindUserID", "attr": username, "err": err}).Debugf("")
		return
	}

	if !VerifyUserPassword(userID, password) {
		c.SetCookie("warning", "Invalid user or password", 0, "/", cfg.Admin.URL, false, true)
		log.WithFields(log.Fields{"call": "VerifyUserPassword", "attr": "***"}).Debugf("auth not ok")
		return
	}

	t := NewSessionToken(userID)

	c.SetCookie("session", t.Encode(), 9999999999, "/", cfg.Admin.URL, false, true)
	c.SetCookie("warning", "", -1, "/", cfg.Admin.URL, false, true)
}
