<?php
namespace Misuzu;

use Misuzu\Parsers\Parser;
use Misuzu\Users\User;

$currentUser = User::getCurrent();

if($currentUser === null) {
    echo render_error(401);
    return;
}

$currentUserId = $currentUser->getId();

if($currentUser->hasActiveWarning()) {
    echo render_error(403);
    return;
}

$forumPostingModes = [
    'create', 'edit', 'quote', 'preview',
];

if(!empty($_POST)) {
    $mode = !empty($_POST['post']['mode']) && is_string($_POST['post']['mode']) ? $_POST['post']['mode'] : 'create';
    $postId = !empty($_POST['post']['id']) && is_string($_POST['post']['id']) ? (int)$_POST['post']['id'] : 0;
    $topicId = !empty($_POST['post']['topic']) && is_string($_POST['post']['topic']) ? (int)$_POST['post']['topic'] : 0;
    $forumId = !empty($_POST['post']['forum']) && is_string($_POST['post']['forum']) ? (int)$_POST['post']['forum'] : 0;
} else {
    $mode = !empty($_GET['m']) && is_string($_GET['m']) ? $_GET['m'] : 'create';
    $postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
    $topicId = !empty($_GET['t']) && is_string($_GET['t']) ? (int)$_GET['t'] : 0;
    $forumId = !empty($_GET['f']) && is_string($_GET['f']) ? (int)$_GET['f'] : 0;
}

if(!in_array($mode, $forumPostingModes, true)) {
    echo render_error(400);
    return;
}

if($mode === 'preview') {
    header('Content-Type: text/plain; charset=utf-8');

    $postText = (string)($_POST['post']['text']);
    $postParser = (int)($_POST['post']['parser']);

    if(!Parser::isValid($postParser)) {
        http_response_code(400);
        return;
    }

    http_response_code(200);
    echo Parser::instance($postParser)->parseText(htmlspecialchars($postText));
    return;
}

if(empty($postId) && empty($topicId) && empty($forumId)) {
    echo render_error(404);
    return;
}

if(!empty($postId)) {
    $post = forum_post_get($postId);

    if(isset($post['topic_id'])) { // should automatic cross-quoting be a thing? if so, check if $topicId is < 1 first
        $topicId = (int)$post['topic_id'];
    }
}

if(!empty($topicId)) {
    $topic = forum_topic_get($topicId);

    if(isset($topic['forum_id'])) {
        $forumId = (int)$topic['forum_id'];
    }
}

if(!empty($forumId)) {
    $forum = forum_get($forumId);
}

if(empty($forum)) {
    echo render_error(404);
    return;
}

$perms = forum_perms_get_user($forum['forum_id'], $currentUserId)[MSZ_FORUM_PERMS_GENERAL];

if($forum['forum_archived']
    || (!empty($topic['topic_locked']) && !perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC))
    || !perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM | MSZ_FORUM_PERM_CREATE_POST)
    || (empty($topic) && !perms_check($perms, MSZ_FORUM_PERM_CREATE_TOPIC))) {
    echo render_error(403);
    return;
}

if(!forum_may_have_topics($forum['forum_type'])) {
    echo render_error(400);
    return;
}

$topicTypes = [];

if($mode === 'create' || $mode === 'edit') {
    $topicTypes[MSZ_TOPIC_TYPE_DISCUSSION] = 'Normal discussion';

    if(perms_check($perms, MSZ_FORUM_PERM_STICKY_TOPIC)) {
        $topicTypes[MSZ_TOPIC_TYPE_STICKY] = 'Sticky topic';
    }
    if(perms_check($perms, MSZ_FORUM_PERM_ANNOUNCE_TOPIC)) {
        $topicTypes[MSZ_TOPIC_TYPE_ANNOUNCEMENT] = 'Announcement';
    }
    if(perms_check($perms, MSZ_FORUM_PERM_GLOBAL_ANNOUNCE_TOPIC)) {
        $topicTypes[MSZ_TOPIC_TYPE_GLOBAL_ANNOUNCEMENT] = 'Global Announcement';
    }
}

// edit mode stuff
if($mode === 'edit') {
    if(empty($post)) {
        echo render_error(404);
        return;
    }

    if(!perms_check($perms, $post['poster_id'] === $currentUserId ? MSZ_FORUM_PERM_EDIT_POST : MSZ_FORUM_PERM_EDIT_ANY_POST)) {
        echo render_error(403);
        return;
    }
}

$notices = [];

if(!empty($_POST)) {
    $topicTitle = $_POST['post']['title'] ?? '';
    $postText = $_POST['post']['text'] ?? '';
    $postParser = (int)($_POST['post']['parser'] ?? Parser::BBCODE);
    $topicType = isset($_POST['post']['type']) ? (int)$_POST['post']['type'] : null;
    $postSignature = isset($_POST['post']['signature']);

    if(!CSRF::validateRequest()) {
        $notices[] = 'Could not verify request.';
    } else {
        $isEditingTopic = empty($topic) || ($mode === 'edit' && $post['is_opening_post']);

        if($mode === 'create') {
            $timeoutCheck = max(1, forum_timeout($forumId, $currentUserId));

            if($timeoutCheck < 5) {
                $notices[] = sprintf("You're posting too quickly! Please wait %s seconds before posting again.", number_format($timeoutCheck));
                $notices[] = "It's possible that your post went through successfully and you pressed the submit button twice by accident.";
            }
        }

        if($isEditingTopic) {
            $originalTopicTitle = $topic['topic_title'] ?? null;
            $topicTitleChanged = $topicTitle !== $originalTopicTitle;
            $originalTopicType = (int)($topic['topic_type'] ?? MSZ_TOPIC_TYPE_DISCUSSION);
            $topicTypeChanged = $topicType !== null && $topicType !== $originalTopicType;

            switch(forum_validate_title($topicTitle)) {
                case 'too-short':
                    $notices[] = 'Topic title was too short.';
                    break;

                case 'too-long':
                    $notices[] = 'Topic title was too long.';
                    break;
            }

            if($mode === 'create' && $topicType === null) {
                $topicType = array_key_first($topicTypes);
            } elseif(!array_key_exists($topicType, $topicTypes) && $topicTypeChanged) {
                $notices[] = 'You are not allowed to set this topic type.';
            }
        }

        if(!Parser::isValid($postParser)) {
            $notices[] = 'Invalid parser selected.';
        }

        switch(forum_validate_post($postText)) {
            case 'too-short':
                $notices[] = 'Post content was too short.';
                break;

            case 'too-long':
                $notices[] = 'Post content was too long.';
                break;
        }

        if(empty($notices)) {
            switch($mode) {
                case 'create':
                    if(!empty($topic)) {
                        forum_topic_bump($topic['topic_id']);
                    } else {
                        $topicId = forum_topic_create(
                            $forum['forum_id'],
                            $currentUserId,
                            $topicTitle,
                            $topicType
                        );
                    }

                    $postId = forum_post_create(
                        $topicId,
                        $forum['forum_id'],
                        $currentUserId,
                        $_SERVER['REMOTE_ADDR'],
                        $postText,
                        $postParser,
                        $postSignature
                    );
                    forum_topic_mark_read($currentUserId, $topicId, $forum['forum_id']);
                    forum_count_increase($forum['forum_id'], empty($topic));
                    break;

                case 'edit':
                    $markUpdated = $post['poster_id'] === $currentUserId
                        && $post['post_created_unix'] < strtotime('-1 minutes')
                        && $postText !== $post['post_text'];

                    if(!forum_post_update($postId, $_SERVER['REMOTE_ADDR'], $postText, $postParser, $postSignature, $markUpdated)) {
                        $notices[] = 'Post edit failed.';
                    }

                    if($isEditingTopic && ($topicTitleChanged || $topicTypeChanged)) {
                        if(!forum_topic_update($topicId, $topicTitle, $topicType)) {
                            $notices[] = 'Topic update failed.';
                        }
                    }
                    break;
            }

            if(empty($notices)) {
                $redirect = url(empty($topic) ? 'forum-topic' : 'forum-post', [
                    'topic' => $topicId ?? 0,
                    'post' => $postId ?? 0,
                    'post_fragment' => 'p' . ($postId ?? 0),
                ]);
                redirect($redirect);
                return;
            }
        }
    }
}

if(!empty($topic)) {
    Template::set('posting_topic', $topic);
}

if($mode === 'edit') { // $post is pretty much sure to be populated at this point
    Template::set('posting_post', $post);
}

$displayInfo = forum_posting_info($currentUserId);

Template::render('forum.posting', [
    'posting_breadcrumbs' => forum_get_breadcrumbs($forumId),
    'global_accent_colour' => forum_get_colour($forumId),
    'posting_forum' => $forum,
    'posting_info' => $displayInfo,
    'posting_notices' => $notices,
    'posting_mode' => $mode,
    'posting_types' => $topicTypes,
    'posting_defaults' => [
        'title' => $topicTitle ?? null,
        'type' => $topicType ?? null,
        'text' => $postText ?? null,
        'parser' => $postParser ?? null,
        'signature' => $postSignature ?? null,
    ],
]);
