// Package router configures web routes.
package router

import (
	"net/http"

	"code.nonshy.com/nonshy/website/pkg/config"
	"code.nonshy.com/nonshy/website/pkg/controller/account"
	"code.nonshy.com/nonshy/website/pkg/controller/admin"
	"code.nonshy.com/nonshy/website/pkg/controller/api"
	"code.nonshy.com/nonshy/website/pkg/controller/api/barertc"
	"code.nonshy.com/nonshy/website/pkg/controller/block"
	"code.nonshy.com/nonshy/website/pkg/controller/chat"
	"code.nonshy.com/nonshy/website/pkg/controller/comment"
	"code.nonshy.com/nonshy/website/pkg/controller/forum"
	"code.nonshy.com/nonshy/website/pkg/controller/friend"
	"code.nonshy.com/nonshy/website/pkg/controller/inbox"
	"code.nonshy.com/nonshy/website/pkg/controller/index"
	"code.nonshy.com/nonshy/website/pkg/controller/photo"
	"code.nonshy.com/nonshy/website/pkg/controller/poll"
	"code.nonshy.com/nonshy/website/pkg/middleware"
)

func New() http.Handler {
	mux := http.NewServeMux()

	// Register controller endpoints.
	mux.HandleFunc("/", index.Create())
	mux.HandleFunc("/favicon.ico", index.Favicon())
	mux.HandleFunc("/about", index.StaticTemplate("about.html")())
	mux.HandleFunc("/features", index.StaticTemplate("features.html")())
	mux.HandleFunc("/faq", index.StaticTemplate("faq.html")())
	mux.HandleFunc("/tos", index.StaticTemplate("tos.html")())
	mux.HandleFunc("/privacy", index.StaticTemplate("privacy.html")())
	mux.HandleFunc("/contact", index.Contact())
	mux.HandleFunc("/login", account.Login())
	mux.HandleFunc("/logout", account.Logout())
	mux.Handle("/signup", middleware.GeoGate(account.Signup()))
	mux.HandleFunc("/forgot-password", account.ForgotPassword())
	mux.HandleFunc("/settings/confirm-email", account.ConfirmEmailChange())
	mux.HandleFunc("/markdown", index.StaticTemplate("markdown.html")())
	mux.HandleFunc("/test/geo-gate", index.StaticTemplate("errors/geo_gate.html")())

	// Login Required. Pages that non-certified users can access.
	mux.Handle("/me", middleware.LoginRequired(account.Dashboard()))
	mux.Handle("/settings", middleware.LoginRequired(account.Settings()))
	mux.Handle("/settings/age-gate", middleware.LoginRequired(account.AgeGate()))
	mux.Handle("/account/two-factor/setup", middleware.LoginRequired(account.Setup2FA()))
	mux.Handle("/account/delete", middleware.LoginRequired(account.Delete()))
	mux.Handle("/account/deactivate", middleware.LoginRequired(account.Deactivate()))
	mux.Handle("/account/reactivate", middleware.LoginRequired(account.Reactivate()))
	mux.Handle("/u/", account.Profile()) // public access OK
	mux.Handle("/photo/upload", middleware.LoginRequired(photo.Upload()))
	mux.Handle("/photo/u/", middleware.LoginRequired(photo.UserPhotos()))
	mux.Handle("/photo/view", middleware.LoginRequired(photo.View()))
	mux.Handle("/photo/edit", middleware.LoginRequired(photo.Edit()))
	mux.Handle("/photo/delete", middleware.LoginRequired(photo.Delete()))
	mux.Handle("/photo/certification", middleware.LoginRequired(photo.Certification()))
	mux.Handle("/photo/private", middleware.LoginRequired(photo.Private()))
	mux.Handle("/photo/private/share", middleware.LoginRequired(photo.Share()))
	mux.Handle("/notes/u/", middleware.LoginRequired(account.UserNotes()))
	mux.Handle("/notes/me", middleware.LoginRequired(account.MyNotes()))
	mux.Handle("/messages", middleware.LoginRequired(inbox.Inbox()))
	mux.Handle("/messages/read/", middleware.LoginRequired(inbox.Inbox()))
	mux.Handle("/messages/compose", middleware.LoginRequired(inbox.Compose()))
	mux.Handle("/messages/delete", middleware.LoginRequired(inbox.Delete()))
	mux.Handle("/friends", middleware.LoginRequired(friend.Friends()))
	mux.Handle("/friends/add", middleware.LoginRequired(friend.AddFriend()))
	mux.Handle("/friends/u/", middleware.CertRequired(account.UserFriends()))
	mux.Handle("/users/block", middleware.LoginRequired(block.BlockUser()))
	mux.Handle("/users/blocked", middleware.LoginRequired(block.Blocked()))
	mux.Handle("/users/blocklist/add", middleware.LoginRequired(block.AddUser()))
	mux.Handle("/comments", middleware.LoginRequired(comment.PostComment()))
	mux.Handle("/comments/subscription", middleware.LoginRequired(comment.Subscription()))
	mux.Handle("/admin/unimpersonate", middleware.LoginRequired(admin.Unimpersonate()))
	mux.Handle("/inner-circle", middleware.LoginRequired(account.InnerCircle()))
	mux.Handle("/inner-circle/invite", middleware.LoginRequired(account.InviteCircle()))

	// Certification Required. Pages that only full (verified) members can access.
	mux.Handle("/photo/gallery", middleware.CertRequired(photo.SiteGallery()))
	mux.Handle("/members", middleware.CertRequired(account.Search()))
	mux.Handle("/chat", middleware.CertRequired(chat.Landing()))
	mux.Handle("/forum", middleware.CertRequired(forum.Landing()))
	mux.Handle("/forum/post", middleware.CertRequired(forum.NewPost()))
	mux.Handle("/forum/thread/", middleware.CertRequired(forum.Thread()))
	mux.Handle("/forum/newest", middleware.CertRequired(forum.Newest()))
	mux.Handle("/f/", middleware.CertRequired(forum.Forum()))
	mux.Handle("/poll/vote", middleware.CertRequired(poll.Vote()))

	// Admin endpoints.
	mux.Handle("/admin", middleware.AdminRequired("", admin.Dashboard()))
	mux.Handle("/admin/scopes", middleware.AdminRequired("", admin.Scopes()))
	mux.Handle("/admin/photo/certification", middleware.AdminRequired("", photo.AdminCertification()))
	mux.Handle("/admin/feedback", middleware.AdminRequired("", admin.Feedback()))
	mux.Handle("/admin/user-action", middleware.AdminRequired("", admin.UserActions()))
	mux.Handle("/admin/maintenance", middleware.AdminRequired(config.ScopeMaintenance, admin.Maintenance()))
	mux.Handle("/forum/admin", middleware.AdminRequired(config.ScopeForumAdmin, forum.Manage()))
	mux.Handle("/forum/admin/edit", middleware.AdminRequired(config.ScopeForumAdmin, forum.AddEdit()))
	mux.Handle("/inner-circle/remove", middleware.LoginRequired(account.RemoveCircle()))

	// JSON API endpoints.
	mux.HandleFunc("/v1/version", api.Version())
	mux.HandleFunc("/v1/users/me", api.LoginOK())
	mux.HandleFunc("/v1/users/check-username", api.UsernameCheck())
	mux.Handle("/v1/likes", middleware.LoginRequired(api.Likes()))
	mux.Handle("/v1/likes/users", middleware.LoginRequired(api.WhoLikes()))
	mux.Handle("/v1/notifications/read", middleware.LoginRequired(api.ReadNotification()))
	mux.Handle("/v1/notifications/delete", middleware.LoginRequired(api.ClearNotification()))
	mux.Handle("/v1/comment-photos/remove-orphaned", api.RemoveOrphanedCommentPhotos())
	mux.Handle("/v1/barertc/report", barertc.Report())
	mux.Handle("/v1/barertc/profile", barertc.Profile())

	// Static files.
	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(config.StaticPath))))

	// Global middlewares.
	withCSRF := middleware.CSRF(mux)
	withSession := middleware.Session(withCSRF)
	withRecovery := middleware.Recovery(withSession)
	withLogger := middleware.Logging(withRecovery)
	return withLogger
}
