package photo

import (
	"net/http"

	"code.nonshy.com/nonshy/website/pkg/config"
	"code.nonshy.com/nonshy/website/pkg/models"
	"code.nonshy.com/nonshy/website/pkg/session"
	"code.nonshy.com/nonshy/website/pkg/templates"
)

// SiteGallery controller (/photo/gallery) to view all members' public gallery pics.
func SiteGallery() http.HandlerFunc {
	tmpl := templates.Must("photo/gallery.html")

	// Whitelist for ordering options.
	var sortWhitelist = []string{
		"created_at desc",
		"created_at asc",
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Query params.
		var (
			viewStyle = r.FormValue("view") // cards (default), full

			// Search filters.
			who              = r.FormValue("who")
			filterExplicit   = r.FormValue("explicit")
			filterVisibility = r.FormValue("visibility")
			adminView        = r.FormValue("admin_view") == "true"
			sort             = r.FormValue("sort")
			sortOK           bool
		)

		// Sort options.
		for _, v := range sortWhitelist {
			if sort == v {
				sortOK = true
				break
			}
		}
		if !sortOK {
			sort = sortWhitelist[0]
		}

		// Load the current user.
		currentUser, err := session.CurrentUser(r)
		if err != nil {
			session.FlashError(w, r, "Unexpected error: couldn't get CurrentUser")
		}

		// Is the current viewer shy?
		var (
			isShy         = currentUser.IsShy()
			myFriendCount = models.CountFriends(currentUser.ID)
		)

		// Defaults.
		if viewStyle != "full" {
			viewStyle = "cards"
		}
		if who != "friends" && who != "everybody" && who != "friends+private" {
			// Default Who setting should be Friends-only, unless you have no friends.
			if myFriendCount > 0 {
				who = "friends"
			} else {
				who = "everybody"
			}
		}

		// Admin scope warning.
		if adminView && !currentUser.HasAdminScope(config.ScopePhotoModerator) {
			session.FlashError(w, r, "Missing admin scope: %s", config.ScopePhotoModerator)
		}

		// Get the page of photos.
		pager := &models.Pagination{
			Page:    1,
			PerPage: config.PageSizeSiteGallery,
			Sort:    sort,
		}
		pager.ParsePage(r)
		photos, _ := models.PaginateGalleryPhotos(currentUser, models.Gallery{
			Explicit:    filterExplicit,
			Visibility:  filterVisibility,
			AdminView:   adminView,
			FriendsOnly: who == "friends",
			IsShy:       isShy || who == "friends+private",
		}, pager)

		// Bulk load the users associated with these photos.
		var userIDs = []uint64{}
		for _, photo := range photos {
			userIDs = append(userIDs, photo.UserID)
		}
		userMap, err := models.MapUsers(currentUser, userIDs)
		if err != nil {
			session.FlashError(w, r, "Failed to MapUsers: %s", err)
		}

		// Get Likes information about these photos.
		var photoIDs = []uint64{}
		for _, p := range photos {
			photoIDs = append(photoIDs, p.ID)
		}
		likeMap := models.MapLikes(currentUser, "photos", photoIDs)
		commentMap := models.MapCommentCounts("photos", photoIDs)

		var vars = map[string]interface{}{
			"IsSiteGallery": true,
			"Photos":        photos,
			"UserMap":       userMap,
			"LikeMap":       likeMap,
			"CommentMap":    commentMap,
			"Pager":         pager,
			"ViewStyle":     viewStyle,

			// Search filters
			"Sort":             sort,
			"FilterWho":        who,
			"FilterExplicit":   filterExplicit,
			"FilterVisibility": filterVisibility,
			"AdminView":        adminView,

			// Is the current user shy?
			"IsShyUser": isShy,
		}

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