package forum

import (
	"net/http"

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

// Forum view for a specific board index.
func Forum() http.HandlerFunc {
	tmpl := templates.Must("forum/board_index.html")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Parse the path parameters
		var (
			forum *models.Forum
		)

		if m := ForumPathRegexp.FindStringSubmatch(r.URL.Path); m == nil {
			log.Error("Regexp failed to parse: %s", r.URL.Path)
			templates.NotFoundPage(w, r)
			return
		} else {
			// Look up the forum itself.
			if found, err := models.ForumByFragment(m[1]); err != nil {
				templates.NotFoundPage(w, r)
				return
			} else {
				forum = found
			}
		}

		// Get the current user.
		currentUser, err := session.CurrentUser(r)
		if err != nil {
			session.FlashError(w, r, "Couldn't get current user: %s", err)
			templates.Redirect(w, "/")
			return
		}

		// Is it an inner circle forum?
		if forum.InnerCircle && !currentUser.IsInnerCircle() {
			templates.NotFoundPage(w, r)
			return
		}

		// Get the pinned threads.
		pinned, err := models.PinnedThreads(forum)
		if err != nil {
			session.FlashError(w, r, "Couldn't get pinned threads: %s", err)
			templates.Redirect(w, "/")
			return
		}

		// Get all the categorized index forums.
		// XXX: we get a large page size to get ALL official forums
		var pager = &models.Pagination{
			Page:    1,
			PerPage: config.PageSizeThreadList,
			Sort:    "updated_at desc",
		}
		pager.ParsePage(r)

		threads, err := models.PaginateThreads(currentUser, forum, pager)
		if err != nil {
			session.FlashError(w, r, "Couldn't paginate threads: %s", err)
			templates.Redirect(w, "/")
			return
		}

		// Inject pinned threads on top.
		threads = append(pinned, threads...)

		// Map the statistics (replies, views) of these threads.
		threadMap := models.MapThreadStatistics(threads)

		var vars = map[string]interface{}{
			"Forum":     forum,
			"Threads":   threads,
			"ThreadMap": threadMap,
			"Pager":     pager,
		}
		if err := tmpl.Execute(w, r, vars); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})
}
