<?php
namespace Misuzu;

use stdClass;
use RuntimeException;

$forum = $msz->getForum();
$users = $msz->getUsers();

$categoryId = (int)filter_input(INPUT_GET, 'f', FILTER_SANITIZE_NUMBER_INT);

try {
    $categoryInfo = $forum->getCategory(categoryId: $categoryId);
} catch(RuntimeException $ex) {
    Template::throwError(404);
}

$perms = $msz->getAuthInfo()->getPerms('forum', $categoryInfo);

$currentUser = $msz->getActiveUser();
$currentUserId = $currentUser === null ? '0' : $currentUser->getId();

if(!$perms->check(Perm::F_CATEGORY_VIEW))
    Template::throwError(403);

if($msz->hasActiveBan())
    $perms = $perms->apply(fn($calc) => $calc & (Perm::F_CATEGORY_LIST | Perm::F_CATEGORY_VIEW));

if($categoryInfo->isLink()) {
    if($categoryInfo->hasLinkTarget()) {
        $forum->incrementCategoryClicks($categoryInfo);
        redirect($categoryInfo->getLinkTarget());
        return;
    }

    Template::throwError(404);
}

$forumPagination = new Pagination($forum->countTopics(
    categoryInfo: $categoryInfo,
    global: true,
    deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false
), 20);

if(!$forumPagination->hasValidOffset())
    Template::throwError(404);

$userInfos = [];
$userColours = [];
$children = [];
$topics = [];

if($categoryInfo->mayHaveChildren()) {
    $children = $forum->getCategoryChildren($categoryInfo, hidden: false, asTree: true);

    foreach($children as $childId => $child) {
        $childPerms = $msz->getAuthInfo()->getPerms('forum', $child->info);
        if(!$childPerms->check(Perm::F_CATEGORY_LIST)) {
            unset($category->children[$childId]);
            continue;
        }

        $childUnread = false;

        if($child->info->mayHaveChildren()) {
            foreach($child->children as $grandChildId => $grandChild) {
                $grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChild->info);
                if(!$grandChildPerms->check(Perm::F_CATEGORY_LIST)) {
                    unset($child->children[$grandChildId]);
                    continue;
                }

                $grandChildUnread = false;

                if($grandChild->info->mayHaveTopics()) {
                    $catIds = [$grandChild->info->getId()];
                    foreach($grandChild->childIds as $greatGrandChildId) {
                        $greatGrandChildPerms = $msz->getAuthInfo()->getPerms('forum', $greatGrandChildId);
                        if(!$greatGrandChildPerms->check(Perm::F_CATEGORY_LIST))
                            $catIds[] = $greatGrandChildId;
                    }

                    $grandChildUnread = $forum->checkCategoryUnread($catIds, $currentUser);
                    if($grandChildUnread)
                        $childUnread = true;
                }

                $grandChild->perms = $grandChildPerms;
                $grandChild->unread = $grandChildUnread;
            }
        }

        if($child->info->mayHaveChildren() || $child->info->mayHaveTopics()) {
            $catIds = [$child->info->getId()];
            foreach($child->childIds as $grandChildId) {
                $grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChildId);
                if($grandChildPerms->check(Perm::F_CATEGORY_LIST))
                    $catIds[] = $grandChildId;
            }

            try {
                $lastPostInfo = $forum->getPost(categoryInfos: $catIds, getLast: true, deleted: false);
            } catch(RuntimeException $ex) {
                $lastPostInfo = null;
            }

            if($lastPostInfo !== null) {
                $child->lastPost = new stdClass;
                $child->lastPost->info = $lastPostInfo;
                $child->lastPost->topicInfo = $forum->getTopic(postInfo: $lastPostInfo);

                if($lastPostInfo->hasUserId()) {
                    $lastPostUserId = $lastPostInfo->getUserId();
                    if(!array_key_exists($lastPostUserId, $userInfos)) {
                        $userInfo = $users->getUser($lastPostUserId, 'id');
                        $userInfos[$lastPostUserId] = $userInfo;
                        $userColours[$lastPostUserId] = $users->getUserColour($userInfo);
                    }

                    $child->lastPost->user = $userInfos[$lastPostUserId];
                    $child->lastPost->colour = $userColours[$lastPostUserId];
                }
            }
        }

        if($child->info->mayHaveTopics() && !$childUnread)
            $childUnread = $forum->checkCategoryUnread($child->info, $currentUser);

        $child->perms = $childPerms;
        $child->unread = $childUnread;
    }
}

if($categoryInfo->mayHaveTopics()) {
    $topicInfos = $forum->getTopics(
        categoryInfo: $categoryInfo,
        global: true,
        deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false,
        pagination: $forumPagination,
    );

    foreach($topicInfos as $topicInfo) {
        $topics[] = $topic = new stdClass;
        $topic->info = $topicInfo;
        $topic->unread = $forum->checkTopicUnread($topicInfo, $currentUser);
        $topic->participated = $forum->checkTopicParticipated($topicInfo, $currentUser);
        $topic->lastPost = new stdClass;

        if($topicInfo->hasUserId()) {
            $lastTopicUserId = $topicInfo->getUserId();
            if(!array_key_exists($lastTopicUserId, $userInfos)) {
                $userInfo = $users->getUser($lastTopicUserId, 'id');
                $userInfos[$lastTopicUserId] = $userInfo;
                $userColours[$lastTopicUserId] = $users->getUserColour($userInfo);
            }

            $topic->user = $userInfos[$lastTopicUserId];
            $topic->colour = $userColours[$lastTopicUserId];
        }

        try {
            $topic->lastPost->info = $lastPostInfo = $forum->getPost(
                topicInfo: $topicInfo,
                getLast: true,
                deleted: $topicInfo->isDeleted() ? null : false,
            );

            if($lastPostInfo->hasUserId()) {
                $lastPostUserId = $lastPostInfo->getUserId();
                if(!array_key_exists($lastPostUserId, $userInfos)) {
                    $userInfo = $users->getUser($lastPostUserId, 'id');
                    $userInfos[$lastPostUserId] = $userInfo;
                    $userColours[$lastPostUserId] = $users->getUserColour($userInfo);
                }

                $topic->lastPost->user = $userInfos[$lastPostUserId];
                $topic->lastPost->colour = $userColours[$lastPostUserId];
            }
        } catch(RuntimeException $ex) {}
    }
}

$perms = $perms->checkMany([
    'can_create_topic' => Perm::F_TOPIC_CREATE,
]);

Template::render('forum.forum', [
    'forum_breadcrumbs' => $forum->getCategoryAncestry($categoryInfo),
    'global_accent_colour' => $forum->getCategoryColour($categoryInfo),
    'forum_info' => $categoryInfo,
    'forum_children' => $children,
    'forum_topics' => $topics,
    'forum_pagination' => $forumPagination,
    'forum_show_mark_as_read' => $currentUser !== null,
    'forum_perms' => $perms,
]);
