<?php

namespace App\Presentation\Posts;
namespace App\Presentation\Articles;

use App\Model\ArticleManager;
use App\Model\EditorManager;
use App\Presentation\BasePresenter;
use Nette\Application\Responses\FileResponse;
use Nette\Http\Session;
use Nette\Http\SessionSection;
use Nette\Utils\Paginator;


final class ArticlesPresenter extends BasePresenter
{
    private ArticleManager $articleManager;
    private EditorManager $editorManager;
    private SessionSection $articleSessions;


    public function __construct(ArticleManager $articleManager, EditorManager $editorManager, Session $session)
    {
        parent::__construct();
        $this->articleManager = $articleManager;

        $this->articleSessions = $session->getSection('mm-articles');
        $this->editorManager = $editorManager;

        // Last opened articles
        if ($this->articleSessions->get('articles_last_opened') == null) {
            $this->articleSessions->set('articles_last_opened', []);
        }
    }

    function renderOpened()
    {
        $articles = $this->articleManager->getPublicArticles()
            ->limit(5, 0)
            ->where('articles.id', $this->articleSessions->get('articles_last_opened'));

        $output = [];
        $opened_articles = [];
        foreach ($articles as $item) {
            if (sizeof($opened_articles) >= 5)
                break;

            if (in_array($item['id'], $opened_articles))
                continue;

            $item_output = [
                "id" => $item['id'],
                "title" => $item['title'],
                "type" => $item['type'],
                "short_description" => $item['short_description'],
                "time_estimate" => $item['time_estimate'],
                "difficulty" => $item['difficulty'],
                "usage_count" => $item['usage_count'],
                "created_at" => $item['created_at'],
                "updated_at" => $item['updated_at'],
                "topic" => $item->topic['topic'],
                "rating" => $item['rating'],
                "author" => $item->users->username
            ];
            $output[] = $item_output;
        }

        $this->sendJson($output);
    }

    function renderGetpostslatest(): void
    {
        $articles = $this->articleManager->getRecentPosts();

        $output = [];
        foreach ($articles as $item) {
            $item_output = [
                "id" => $item['id'],
                "title" => $item['title'],
                "type" => $item['type'],
                "short_description" => $item['short_description'],
                "time_estimate" => $item['time_estimate'],
                "difficulty" => $item['difficulty'],
                "usage_count" => $item['usage_count'],
                "created_at" => $item['created_at'],
                "updated_at" => $item['updated_at'],
                "topic" => $item->topic['topic'],
                "rating" => $item['rating'],
                "author" => $item->users->username
            ];
            $output[] = $item_output;
        }
        $this->sendJson($output);
    }

    public function renderAllArticles($page = 1, $difficulty = null, $contentType = null, $input = null, $topic = null, $status = null): void
    {
        if (!$this->getUser()->isLoggedIn() || !$this->getUser()->isAllowed('article', 'display-all')) {

        }
        $selection = $this->articleManager->getAllArticles();
        if ($status != null)
        {
            $selection->where('status', $status);
        }
        $this->processDisplayArticles($selection, $page, $difficulty, $contentType, $input, $topic);
    }

    public function renderPublicArticles($page = 1, $difficulty = null, $contentType = null, $input = null, $topic = null): void
    {
        $selection = $this->articleManager->getPublicArticles();
        $this->processDisplayArticles($selection, $page, $difficulty, $contentType, $input, $topic);
    }

    public function processDisplayArticles($selection, $page = 1, $difficulty = null, $contentType = null, $input = null, $topic = null): void
    {
        if ($difficulty != null) {
            $selection->where('difficulty', $difficulty);
        }

        if ($contentType != null) {
            $selection->where('type', $contentType);
        }

        if ($input != null) {
            $selection->where('title LIKE ?', '%' . $input . '%');
        }

        if ($topic != null) {
            $selection->where('topic.topic', $topic);
        }

        $paginator = new Paginator();
        $paginator->setPage($page);
        $paginator->setItemsPerPage(20);
        $paginator->setItemCount($selection->count());

        $articles = $selection->limit($paginator->getLength(), $paginator->getOffset());

        $output = [
            'page' => $paginator->getPage(),
            'pages_count' => $paginator->getPageCount(),
            'articles_count' => $paginator->getItemCount(),
            'articles' => []
        ];

        foreach ($articles as $item) {
            $item_output = [
                "id" => $item['id'],
                "title" => $item['title'],
                "type" => $item['type'],
                "short_description" => $item['short_description'],
                "time_estimate" => $item['time_estimate'],
                "difficulty" => $item['difficulty'],
                "usage_count" => $item['usage_count'],
                "created_at" => $item['created_at'],
                "updated_at" => $item['updated_at'],
                "topic" => $item->topic['topic'],
                "rating" => $item['rating'],
                "status" => $item['status'],
                "author" => $item->users->username
            ];
            $output['articles'][] = $item_output;
        }
        $this->sendJson($output);
    }

    public function renderGetselfArticles($page = 1)
    {
        if (!$this->getUser()->isLoggedIn())
            $this->error("User is not logged in", 403);

        $selection = $this->articleManager->getAllArticles()
            ->where('users_id', $this->getUser()->getId());

        $paginator = new Paginator();
        $paginator->setPage($page);
        $paginator->setItemsPerPage(20);
        $paginator->setItemCount($selection->count());

        $articles = $selection->limit($paginator->getLength(), $paginator->getOffset());

        $output = [
            'page' => $paginator->getPage(),
            'pages_count' => $paginator->getPageCount(),
            'articles_count' => $paginator->getItemCount(),
            'articles' => []
        ];

        foreach ($articles as $item) {
            $item_output = [
                "id" => $item['id'],
                "title" => $item['title'],
                "type" => $item['type'],
                "short_description" => $item['short_description'],
                "time_estimate" => $item['time_estimate'],
                "difficulty" => $item['difficulty'],
                "usage_count" => $item['usage_count'],
                "created_at" => $item['created_at'],
                "updated_at" => $item['updated_at'],
                "topic" => $item->topic['topic'],
                "rating" => $item['rating'],
                "author" => $item->users->username,
                "status" => $item['status']
            ];
            $output['articles'][] = $item_output;
        }
        $this->sendJson($output);
    }

    function renderGetarticle(int $articleId): void
    {
        // sanity check
        if ($articleId == null || !is_numeric($articleId))
            $this->error("Invalid article ID", 403);


        $article = $this->articleManager->getApprovedArticle($articleId);

        if ($article == null || !$article->count())
            $this->error("Article was not found.", 404);

        $output = [];

        $this->prepareObjectOutput(
            $output,
            $article,
            ["id", "title", "type", "short_description", "content", "time_estimate", "difficulty", "usage_count", "created_at"]
        );
        $output['content'] = json_decode($output['content']);

        $output['comments'] = [];
        foreach ($this->articleManager->getComments($articleId) as $comment) {
            $comment_output = [
                'id' => $comment['id'],
                'parent_comment_id' => $comment['parent_comment_id'],
                'text' => $comment['text'],
                'author' => $comment['author'],
                'created_at' => $comment['created_at'],
                'can_add_reaction' => rand(1, 2) == 1,
                'child_comments' => []
            ];

            if ($comment['parent_comment_id'] == null) {
                $output['comments'][] = $comment_output;
            } else {
                $this->addCommentToParent($output['comments'], $comment_output);
            }
        }

        $output['files'] = [];
        $this->prepareObjectsOutput($output['files'], $this->articleManager->getFiles($articleId), ['id', 'name']);

        $opened_articles = $this->articleSessions->get('articles_last_opened');

        if ($this->getUser()->isLoggedIn() && !in_array($output['id'], $opened_articles)) {
            $this->articleManager->userSawArticle($this->getUser()->getId(), $articleId);
        }

        $opened_articles[] = $output['id'];
        $this->articleSessions->set('articles_last_opened', $opened_articles);

        $this->sendJson($output);
    }

    private function addCommentToParent(array &$comments, &$new_comment): bool
    {
        foreach ($comments as &$comment) {
            if ($comment['id'] == $new_comment['parent_comment_id']) {
                $comment['child_comments'][] = $new_comment;
                return true;
            }

            if ($this->addCommentToParent($comment['child_comments'], $new_comment)) {
                return true;
            }
        }
        return false;
    }

    function renderGettopics(): void
    {
        $output = [];

        foreach ($this->articleManager->getTopics() as $topic) {
            if (!array_key_exists($topic->topic, $output))
            {
                $output[$topic->topic] = [];
            }
            if (strlen($topic->subtopic) > 0)
                $output[$topic->topic][] =
                    [
                        'id' => $topic->id,
                        'subtopic' => $topic->subtopic,

                    ];
        }

        $this->sendJson($output);
    }


    function actionGetfile($articleId, $fileId): void
    {
        $fileRow = $this->articleManager->getFile($articleId, $fileId);
        if (!$fileRow) {
            $this->error("File was not found", 404);
        }

        $filePath = $this->editorManager->getArticleFilesPath() . $fileRow->path;
        $response = new FileResponse($filePath, $fileRow->name);
        $this->sendResponse($response);
    }
}


