<?php
namespace Newland\Toubiz\Poi\Neos\Controller;

/*
 * This file is part of the "toubiz-poi-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Neos\ContentRepository\Domain\Model\Node;
use Neos\Flow\Annotations as Flow;
use Newland\NeosCommon\Service\NodeService;
use Newland\Toubiz\Poi\Neos\Domain\Repository\TopicRepository;
use Newland\Toubiz\Poi\Neos\Filter\ArticleFilterFactory;

class FilteredListsController extends AbstractActionController
{
    /**
     * @var TopicRepository
     * @Flow\Inject()
     */
    protected $topicRepository;

    /**
     * @var NodeService
     * @Flow\Inject()
     */
    protected $nodeService;

    /**
     * Renders the `Newland.Toubiz.Poi.Neos:FilteredLists` NodeTypes and children.
     * @deprecated This node is deprecated since 1.13, will be disabled by default starting in 1.14 and removed in 1.15
     */
    public function indexAction(): void
    {
        $articleType = $this->properties['articleType'];
        $filter = (new ArticleFilterFactory($this->node))
            ->createFilterForArticleType($articleType, $this->properties)
            ->initializeForFilteredLists($this->request);

        $topics = $this->topicRepository->findByIdentifiers($this->properties['topics'] ?? []);
        $lists = $this->topicRepository->findByIdentifiers($this->properties['lists'] ?? []);

        $this->view->assignMultiple(
            [
                'filter' => $filter,
                'topics' => $topics,
                'lists' => $lists,
                'properties' => $this->properties,
                'listLimit' => $this->properties['listLimit'] ?? 11,
                'documentNode' => $this->nodeService->getDocumentNode($this->node),
            ]
        );
    }

    public function showAction(Node $node = null, string $layout = 'teaser'): void
    {
        // For AJAX requests we need to set the node manually and re-parse the properties, etc.
        $this->initializeNode($node);

        $articleType = $this->properties['articleType'];
        $filter = (new ArticleFilterFactory($this->node))
            ->createFilterForArticleType($articleType, $this->properties)
            ->initializeForFilteredLists($this->request)
            ->setPageSize($this->settings['gridItemsPerPage']);

        $hideFilters = $this->properties['hideFilters'] ?? false;

        $count = $filter->countArticles();
        $articles = $filter
            ->setPageSize($this->settings['gridItemsPerPage'])
            ->getArticleQuery()
            ->getQuery()
            ->execute();

        $page = $this->getCurrentPageNumberFromRequest();
        $pages = ceil($count / $this->settings['gridItemsPerPage']);

        $this->view->assignMultiple(
            [
                'filter' => $filter,
                'articles' => $articles,
                'count' => $count,
                'format' => $node ? 'ajax' : 'html',
                'layout' => $layout,
                'hideFilters' => $hideFilters,
                'pagination' => [
                    'isFirst' => $page === 1,
                    'page' => $page,
                    'isLast' => $pages === $page,
                    'count' => [
                        'items' => $count,
                        'pages' => $pages,
                    ],
                ],
            ]
        );
    }

    public function showTeaserListAction(): void
    {
        $this->initializeNode();

        $articleType = $this->properties['articleType'];
        $filter = (new ArticleFilterFactory($this->node))
            ->createFilterForArticleType($articleType, $this->properties)
            ->initializeForFilteredLists($this->request);

        $count = $filter->countArticles();
        $articles = $filter
            ->getArticleQuery()
            ->setMaxResults($this->settings['listItemsPerPage'])
            ->getQuery()
            ->execute();

        $listTarget = $this->properties['listTarget'] ?? null;
        /*
         * If a property is cleared in neos, it saves an empty string.
         * Catch that case and return null:
         */
        $listTarget = $listTarget ?: null;

        $listUri = $filter->getListUri(
            $this->getControllerContext(),
            $this->properties,
            $listTarget
        );
        $this->view->assignMultiple(
            [
                'title' => $this->properties['title'] ?? '',
                'articles' => $articles,
                'count' => $count,
                'listUri' => $listUri,
            ]
        );
    }

    public function linkAction(): void
    {
        $this->initializeNode();

        $articleType = $this->properties['articleType'];
        $filter = (new ArticleFilterFactory($this->node))
            ->createFilterForArticleType($articleType, $this->properties)
            ->initializeForFilteredLists($this->request);

        $listUri = $filter->getListUri(
            $this->getControllerContext(),
            $this->properties,
            $this->properties['listTarget'] ?? null
        );
        $this->view->assignMultiple(
            [
                'title' => $this->properties['title'] ?? '',
                'listUri' => $listUri,
            ]
        );
    }

    private function getCurrentPageNumberFromRequest(string $argument = 'page'): int
    {
        if (!$this->request->getMainRequest()->hasArgument($argument)) {
            return 1;
        }

        return max(1, (int) $this->request->getMainRequest()->getArgument($argument));
    }
}
