package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/gorilla/securecookie"
	"net/http"
)

// cookie handling

var cookieHandler = securecookie.New(
	securecookie.GenerateRandomKey(64),
	securecookie.GenerateRandomKey(32))

func getUserName(request *http.Request) (userName string) {
	if cookie, err := request.Cookie("session"); err == nil {
		cookieValue := make(map[string]string)
		if err = cookieHandler.Decode("session", cookie.Value, &cookieValue); err == nil {
			userName = cookieValue["name"]
		}
	}
	return userName
}

func getUserNameHash(request *http.Request) (userName string) {
	if cookie, err := request.Cookie("session"); err == nil {
		cookieValue := make(map[string]string)
		if err = cookieHandler.Decode("session", cookie.Value, &cookieValue); err == nil {
			userName = cookieValue["name"]
		}
	}
	hasher := md5.New()
	hasher.Write([]byte(userName))
	return hex.EncodeToString(hasher.Sum(nil))
}

func setSession(userName string, response http.ResponseWriter) {
	value := map[string]string{
		"name": userName,
	}
	if encoded, err := cookieHandler.Encode("session", value); err == nil {
		cookie := &http.Cookie{
			Name:  "session",
			Value: encoded,
			Path:  "/",
		}
		http.SetCookie(response, cookie)
	}
}

func clearSession(response http.ResponseWriter) {
	cookie := &http.Cookie{
		Name:   "session",
		Value:  "",
		Path:   "/",
		MaxAge: -1,
	}
	http.SetCookie(response, cookie)
}

// login handler

func loginHandler(response http.ResponseWriter, request *http.Request) {
	name := request.FormValue("email")
	pass := request.FormValue("password")
	redirectTarget := "/invalid_login.html"
	// .. check credentials ..
	if checkLoginCredentials(name, pass) {
		redirectTarget = "/scales.html"
		logit(fmt.Sprintf("loginHandler: successful login for User %s", name))
		setSession(name, response)
		updateLoginTime(name)
	} else {
		logit(fmt.Sprintf("loginHandler: invalid login for User %s", name))
	}
	http.Redirect(response, request, redirectTarget, 302)
}

// resetPassword handler

func resetPasswordHandler(response http.ResponseWriter, request *http.Request) {
	name := request.FormValue("email")
	pass := request.FormValue("password")
	redirectTarget := "/wait_for_password_confirmation.html"
	logit(fmt.Sprintf("resetPasswordHandler: request for User %s", name))
	if name != "" && pass != "" {
		if checkUserAvailable(name) {
			http.Redirect(response, request, "/user_does_not_exist.html", 302)
		} else {
			updateUser(name, pass)
			http.Redirect(response, request, redirectTarget, 302)
		}
	}
	http.Redirect(response, request, "/error_reset_password.html", 302)
}

// setPassword handler

func setPasswordHandler(response http.ResponseWriter, request *http.Request) {
	name := getUserName(request)
	pass := request.FormValue("password")
	if name != "" && pass != "" {
		if checkUserAvailable(name) {
			http.Redirect(response, request, "/user_does_not_exist.html", 302)
		} else {
			updateUser(name, pass)
		}
	}
}

// logout handler

func logoutHandler(response http.ResponseWriter, request *http.Request) {
	clearSession(response)
	http.Redirect(response, request, "/", 302)
}

// confirm handler

func confirmHandler(response http.ResponseWriter, request *http.Request) {
	confirm_id := request.URL.Query().Get("id")
	logit(fmt.Sprintf("Confirm ID: %s\n", confirm_id))
	if confirmUser(confirm_id) {
		http.Redirect(response, request, "/password_changed.html", 302)
	} else {
		http.Redirect(response, request, "/", 302)
	}
}
