package photo

import (
	"net/http"
	"regexp"

	"git.kirsle.net/apps/gosocial/pkg/config"
	"git.kirsle.net/apps/gosocial/pkg/models"
	"git.kirsle.net/apps/gosocial/pkg/session"
	"git.kirsle.net/apps/gosocial/pkg/templates"
)

var UserPhotosRegexp = regexp.MustCompile(`^/photo/u/([^@]+?)$`)

// UserPhotos controller (/photo/u/:username) to view a user's gallery or manage if it's yourself.
func UserPhotos() http.HandlerFunc {
	tmpl := templates.Must("photo/gallery.html")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Query params.
		var (
			viewStyle = r.FormValue("view") // cards (default), full
		)
		if viewStyle != "full" {
			viewStyle = "cards"
		}

		// Parse the username out of the URL parameters.
		var username string
		m := UserPhotosRegexp.FindStringSubmatch(r.URL.Path)
		if m != nil {
			username = m[1]
		}

		// Find this user.
		user, err := models.FindUser(username)
		if err != nil {
			templates.NotFoundPage(w, r)
			return
		}

		// Load the current user in case they are viewing their own page.
		currentUser, err := session.CurrentUser(r)
		if err != nil {
			session.FlashError(w, r, "Unexpected error: couldn't get CurrentUser")
		}
		var isOwnPhotos = currentUser.ID == user.ID

		// Is either one blocking?
		if models.IsBlocking(currentUser.ID, user.ID) && !currentUser.IsAdmin {
			templates.NotFoundPage(w, r)
			return
		}

		// Is this user private and we're not friends?
		var (
			areFriends = models.AreFriends(user.ID, currentUser.ID)
			isPrivate  = user.Visibility == models.UserVisibilityPrivate && !areFriends
		)
		if isPrivate && !currentUser.IsAdmin && !isOwnPhotos {
			session.FlashError(w, r, "This user's profile page and photo gallery are private.")
			templates.Redirect(w, "/u/"+user.Username)
			return
		}

		// What set of visibilities to query?
		visibility := []models.PhotoVisibility{models.PhotoPublic}
		if isOwnPhotos || currentUser.IsAdmin {
			visibility = append(visibility, models.PhotoFriends, models.PhotoPrivate)
		} else if models.AreFriends(user.ID, currentUser.ID) {
			visibility = append(visibility, models.PhotoFriends)
		}

		// Explicit photo filter?
		explicit := currentUser.Explicit
		if isOwnPhotos {
			explicit = true
		}

		// Get the page of photos.
		pager := &models.Pagination{
			Page:    1,
			PerPage: config.PageSizeUserGallery,
			Sort:    "created_at desc",
		}
		pager.ParsePage(r)
		photos, err := models.PaginateUserPhotos(user.ID, visibility, explicit, pager)

		// Get the count of explicit photos if we are not viewing explicit photos.
		var explicitCount int64
		if !explicit {
			explicitCount, _ = models.CountExplicitPhotos(user.ID, visibility)
		}

		var vars = map[string]interface{}{
			"IsOwnPhotos":   currentUser.ID == user.ID,
			"User":          user,
			"Photos":        photos,
			"Pager":         pager,
			"ViewStyle":     viewStyle,
			"ExplicitCount": explicitCount,
		}

		if err := tmpl.Execute(w, r, vars); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})
}
