<?php
namespace Misuzu\Http\Handlers;

use Misuzu\Config;
use Misuzu\Config\CfgType;
use Misuzu\DB;
use Misuzu\Pagination;
use Misuzu\Template;
use Misuzu\Feeds\Feed;
use Misuzu\Feeds\FeedItem;
use Misuzu\Feeds\AtomFeedSerializer;
use Misuzu\Feeds\RssFeedSerializer;
use Misuzu\News\NewsCategory;
use Misuzu\News\NewsPost;
use Misuzu\News\NewsCategoryNotFoundException;
use Misuzu\News\NewsPostNotFoundException;
use Misuzu\Parsers\Parser;
use Misuzu\Users\User;

final class NewsHandler extends Handler {
    public function index($response, $request) {
        $categories = NewsCategory::all();
        $newsPagination = new Pagination(NewsPost::countAll(true), 5);

        if(!$newsPagination->hasValidOffset())
            return 404;

        $response->setContent(Template::renderRaw('news.index', [
            'categories' => $categories,
            'posts' => NewsPost::all($newsPagination, true),
            'news_pagination' => $newsPagination,
        ]));
    }

    public function viewCategory($response, $request, string $fileName) {
        $categoryId = (int)pathinfo($fileName, PATHINFO_FILENAME);
        $type = pathinfo($fileName, PATHINFO_EXTENSION);

        try {
            $categoryInfo = NewsCategory::byId($categoryId);
        } catch(NewsCategoryNotFoundException $ex) {
            return 404;
        }

        if($type === 'atom')
            return $this->feedCategoryAtom($response, $request, $categoryInfo);
        elseif($type === 'rss')
            return $this->feedCategoryRss($response, $request, $categoryInfo);
        elseif($type !== '')
            return 404;

        $categoryPagination = new Pagination(NewsPost::countByCategory($categoryInfo), 5);
        if(!$categoryPagination->hasValidOffset())
            return 404;

        $response->setContent(Template::renderRaw('news.category', [
            'category_info' => $categoryInfo,
            'posts' => $categoryInfo->posts($categoryPagination),
            'news_pagination' => $categoryPagination,
        ]));
    }

    public function viewPost($response, $request, int $postId) {
        try {
            $postInfo = NewsPost::byId($postId);
        } catch(NewsPostNotFoundException $ex) {
            return 404;
        }

        if(!$postInfo->isPublished() || $postInfo->isDeleted())
            return 404;

        $postInfo->ensureCommentsCategory();
        $commentsInfo = $postInfo->getCommentsCategory();

        $response->setContent(Template::renderRaw('news.post', [
            'post_info' => $postInfo,
            'comments_info'  => $commentsInfo,
            'comments_user'  => User::getCurrent(),
        ]));
    }

    private function createFeed(string $feedMode, ?NewsCategory $categoryInfo, array $posts): Feed {
        $hasCategory = !empty($categoryInfo);
        $pagination = new Pagination(10);
        $posts = $hasCategory ? $categoryInfo->posts($pagination) : NewsPost::all($pagination, true);

        $feed = (new Feed)
            ->setTitle(Config::get('site.name', CfgType::T_STR, 'Misuzu') . ' » ' . ($hasCategory ? $categoryInfo->getName() : 'Featured News'))
            ->setDescription($hasCategory ? $categoryInfo->getDescription() : 'A live featured news feed.')
            ->setContentUrl(url_prefix(false) . ($hasCategory ? url('news-category', ['category' => $categoryInfo->getId()]) : url('news-index')))
            ->setFeedUrl(url_prefix(false) . ($hasCategory ? url("news-category-feed-{$feedMode}", ['category' => $categoryInfo->getId()]) : url("news-feed-{$feedMode}")));

        foreach($posts as $post) {
            $postUrl = url_prefix(false) . url('news-post', ['post' => $post->getId()]);
            $commentsUrl = url_prefix(false) . url('news-post-comments', ['post' => $post->getId()]);
            $authorUrl = url_prefix(false) . url('user-profile', ['user' => $post->getUser()->getId()]);

            $feedItem = (new FeedItem)
                ->setTitle($post->getTitle())
                ->setSummary($post->getFirstParagraph())
                ->setContent(Parser::instance(Parser::MARKDOWN)->parseText($post->getText()))
                ->setCreationDate($post->getCreatedTime())
                ->setUniqueId($postUrl)
                ->setContentUrl($postUrl)
                ->setCommentsUrl($commentsUrl)
                ->setAuthorName($post->getUser()->getUsername())
                ->setAuthorUrl($authorUrl);

            if(!$feed->hasLastUpdate() || $feed->getLastUpdate() < $feedItem->getCreationDate())
                $feed->setLastUpdate($feedItem->getCreationDate());

            $feed->addItem($feedItem);
        }

        return $feed;
    }

    public function feedIndexAtom($response, $request) {
        $response->setContentType('application/atom+xml; charset=utf-8');
        return (new AtomFeedSerializer)->serializeFeed(
            self::createFeed('atom', null, NewsPost::all(new Pagination(10), true))
        );
    }

    public function feedIndexRss($response, $request) {
        $response->setContentType('application/rss+xml; charset=utf-8');
        return (new RssFeedSerializer)->serializeFeed(
            self::createFeed('rss', null, NewsPost::all(new Pagination(10), true))
        );
    }

    public function feedCategoryAtom($response, $request, NewsCategory $categoryInfo) {
        $response->setContentType('application/atom+xml; charset=utf-8');
        return (new AtomFeedSerializer)->serializeFeed(
            self::createFeed('atom', $categoryInfo, $categoryInfo->posts(new Pagination(10)))
        );
    }

    public function feedCategoryRss($response, $request, NewsCategory $categoryInfo) {
        $response->setContentType('application/rss+xml; charset=utf-8');
        return (new RssFeedSerializer)->serializeFeed(
            self::createFeed('rss', $categoryInfo, $categoryInfo->posts(new Pagination(10)))
        );
    }
}
