<?php

namespace SGalinski\SgNews\Controller;

/***************************************************************
 *  Copyright notice
 *
 *  (c) sgalinski Internet Services (https://www.sgalinski.de)
 *
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/

use SGalinski\SgNews\Domain\Model\Category;
use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Model\Tag;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Service\ConfigurationService;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Http\ImmediateResponseException;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Query;
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;

/**
 * Controller that handles the overview page of categories and their news
 */
class OverviewController extends AbstractController {
	/**
	 * @var CategoryRepository
	 */
	protected $categoryRepository;

	/**
	 * @var TagRepository
	 */
	protected $tagRepository;

	/**
	 * @var NewsRepository
	 */
	protected $newsRepository;

	/**
	 * @param CategoryRepository $categoryRepository
	 */
	public function injectCategoryRepository(
		CategoryRepository $categoryRepository
	) {
		$this->categoryRepository = $categoryRepository;
	}

	/**
	 * @param NewsRepository $newsRepository
	 */
	public function injectNewsRepository(NewsRepository $newsRepository) {
		$this->newsRepository = $newsRepository;
	}

	/**
	 * @param TagRepository $tagRepository
	 */
	public function injectTagRepository(TagRepository $tagRepository) {
		$this->tagRepository = $tagRepository;
	}

	/**
	 * Initialize the overviewAction to set the currentPageBrowserPage parameter
	 *
	 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
	 */
	public function initializeOverviewAction() {
		$currentPageBrowserPage = GeneralUtility::_GP('tx_sgnews_pagebrowser') ? (int) GeneralUtility::_GP(
			'tx_sgnews_pagebrowser'
		)['currentPage'] : 0;
		if ($currentPageBrowserPage > 0) {
			$this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage);
		}
	}

	/**
	 * Renders the news overview
	 *
	 * @param array $newsFilter
	 * @param int $currentPageBrowserPage
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
	 */
	public function overviewAction(array $newsFilter = [], int $currentPageBrowserPage = 0
	): ?\Psr\Http\Message\ResponseInterface {
		switch ((int) $this->settings['groupBy']) {
			case 1:
				$this->overviewWithCategories([], [], $newsFilter, $currentPageBrowserPage);
				break;
			case 2:
				$this->overviewWithTags([], [], $newsFilter, $currentPageBrowserPage);
				break;
			default:
				if (version_compare(
					\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<'
				)) {
					$this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments());
				} else {
					return (new \TYPO3\CMS\Extbase\Http\ForwardResponse(
						'overviewWithoutCategories'
					))->withControllerName('Record')
						->withExtensionName('Extension')
						->withArguments($this->request->getArguments());
				}
				break;
		}

		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
			return NULL;
		} else {
			return $this->htmlResponse();
		}
	}

	/**
	 * Highlights the best fitting news in the metadata of the page
	 *
	 * @param array|null $categoryIds
	 * @param array|null $tagIds
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 */
	protected function highlightBestFitNews(array $categoryIds = NULL, array $tagIds = NULL) {
		$startTime = 0;
		if (isset($this->settings['starttime'])) {
			$startTime = (int) $this->settings['starttime'];
		}

		$endTime = 0;
		if (isset($this->settings['endtime'])) {
			$endTime = (int) $this->settings['endtime'];
		}

		/** @var News $highlightedNews */
		$highlightedNews = $this->newsRepository
			->findLastUpdatedOrHighlightedNewsByCategories(
				1,
				FALSE,
				$categoryIds,
				0,
				FALSE,
				$this->settings['sortBy'],
				$tagIds,
				$startTime,
				$endTime
			)->getFirst();
		if (!$highlightedNews) {
			return;
		}

		/** @var Category $category */
		$category = $this->categoryRepository->findByUid($highlightedNews->getPid());
		$highlightedNewsMetaData = NULL;
		if ($category) {
			$highlightedNewsMetaData = $this->getMetaDataForNews($highlightedNews, $category);
		}

		if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) {
			if (isset($highlightedNewsMetaData['imageObject'])) {
				HeaderMetaDataService::addOgImageObjectToHeader(
					$highlightedNewsMetaData['imageObject']
						? $highlightedNewsMetaData['imageObject']->getOriginalResource()
						: NULL
				);
			} elseif (isset($highlightedNewsMetaData['teaserImageObject'])) {
				HeaderMetaDataService::addOgImageObjectToHeader(
					$highlightedNewsMetaData['teaserImageObject']
						? $highlightedNewsMetaData['teaserImageObject']->getOriginalResource()
						: NULL
				);
			}
		}
	}

	/**
	 * Renders the news overview grouped by categories
	 *
	 * @param array $newsByCategory
	 * @param array $allNews
	 * @param array $newsFilter
	 * @param int $currentPageBrowserPage
	 * @return void
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
	 * @throws ImmediateResponseException
	 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
	 */
	protected function overviewWithCategories(
		array $newsByCategory = [],
		array $allNews = [],
		array $newsFilter = [],
		int $currentPageBrowserPage = 0
	) {
		$newsLimitPerCategory = (int) $this->settings['newsLimit'];
		$this->categoryRepository->setDefaultOrderings(['sorting' => Query::ORDER_ASCENDING]);

		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimitPerCategory);

		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
		} else {
			$categories = $this->categoryRepository->findAll()->toArray();
		}

		if (count($categories) <= 0) {
			return;
		}

		if (isset($this->settings['categoryRestrictions'])) {
			$categoryRestrictions = GeneralUtility::intExplode(',', $this->settings['categoryRestrictions'], TRUE);
			if (count($categoryRestrictions) > 0) {
				foreach ($categories as $key => $category) {
					$categoryId = $category->getUid();

					// older version compatibility with selection of categories in translations and so on
					$categoryIdTranslated = $categoryId;
					if ($category->_getProperty('_languageUid') > 0) {
						$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($categoryId);
						if ($originalLangCategory) {
							$categoryIdTranslated = $originalLangCategory->getUid();
						}
					}

					if (!in_array($categoryId, $categoryRestrictions, TRUE) &&
						!in_array($categoryIdTranslated, $categoryRestrictions, TRUE)
					) {
						unset($categories[$key]);
					}
				}
			}
		}

		if (count($categories) <= 0) {
			return;
		}

		$startTime = 0;
		if (isset($this->settings['starttime'])) {
			$startTime = (int) $this->settings['starttime'];
		}

		$endTime = 0;
		if (isset($this->settings['endtime'])) {
			$endTime = (int) $this->settings['endtime'];
		}

		$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
		$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
		$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);

		$categoryIds = [];
		$categoriesById = [];
		$newsMetaData = [];
		foreach ($categories as $category) {
			/** @var Category $category */
			$categoryId = $category->getUid();
			$categoryIdsForSelect = [$categoryId];
			$categoryIds[] = $category->getUid();
			$categoriesById[$categoryId] = $category;
			if ($category->_getProperty('_languageUid') > 0) {
				$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($category->getUid());
				if ($originalLangCategory) {
					$originalLangCategoryId = $originalLangCategory->getUid();
					$categoryIdsForSelect[] = $originalLangCategoryId;
					$categoryIds[] = $originalLangCategoryId;
					$categoriesById[$originalLangCategoryId] = $originalLangCategory;
				}
			}

			$tagIds = NULL;
			if (isset($newsFilter['tag']) && $newsFilter['tag']) {
				$tagIds = [(int) $newsFilter['tag']];
			}
			foreach ($categoryIdsForSelect as $categoryIdsForSelectId) {
				$news = $this->newsRepository->findAllSortedNewsByCategories(
					[$categoryIdsForSelectId],
					$newsLimitPerCategory,
					$offset,
					$sortBy,
					$tagIds,
					$startTime,
					$endTime,
					$sortDirection
				);

				$newsMetaData[$categoryIdsForSelectId] = [];
				foreach ($news as $newsEntry) {
					/** @var News $newsEntry */
					$category = $categoriesById[$categoryIdsForSelectId];
					if (!$category) {
						// Category isn't visible.
						continue;
					}

					$data = $this->getMetaDataForNews($newsEntry, $category);
					$newsMetaData[$categoryIdsForSelectId][] = $data;
				}
			}
		}

		$maxNewsPerCategory = 0;
		foreach ($categoriesById as $categoryId => $category) {
			if (!isset($newsMetaData[$categoryId]) || count($newsMetaData[$categoryId]) <= 0) {
				// Hide empty categories.
				continue;
			}

			/** @var Category $category */
			if (isset($newsByCategory[$categoryId])) {
				/** @var Category $category */
				$newsByCategory[$categoryId]['newsMetaData'] =
					array_merge($newsByCategory[$categoryId]['newsMetaData'], $newsMetaData[$categoryId], $newsFilter);
			} else {
				$newsByCategory[$categoryId] = [
					'record' => $category,
					'recordId' => $categoryId,
					'recordType' => 'category',
					'newsMetaData' => $newsMetaData[$categoryId],
					'newsCount' => count($newsMetaData[$categoryId])
				];
			}

			$maxNewsPerCategory = \max($maxNewsPerCategory, \count($newsByCategory[$categoryId]['newsMetaData']));
		}

		$tagIds = NULL;
		if (isset($newsFilter['tag']) && $newsFilter['tag']) {
			$tagIds = [(int) $newsFilter['tag']];
		}
		if ($newsFilter['category']) {
			$categoryIds = [(int) $newsFilter['category']];
		}
		$news = $this->newsRepository->findAllSortedNewsByCategories(
			$categoryIds,
			$newsLimitPerCategory,
			$offset,
			$sortBy,
			$tagIds,
			$startTime,
			$endTime,
			$sortDirection
		);

		foreach ($news as $newsEntry) {
			/** @var News $newsEntry */
			$categoryId = $newsEntry->getPid();
			$category = $categoriesById[$categoryId];
			if (!$category) {
				// Category isn't visible.
				continue;
			}

			$data = $this->getMetaDataForNews($newsEntry, $category);
			$allNews[] = $data;
		}

		$this->highlightBestFitNews($categoryIds);

		$newsCount = $this->newsRepository->newsCountByCategories($categoryIds, $tagIds, $startTime, $endTime);
		$numberOfPages = (int) ($newsLimitPerCategory <= 0 ? 0 : ceil($newsCount / $newsLimitPerCategory));
		if ($numberOfPages !== 0 && $currentPageBrowserPage >= $numberOfPages) {
			/** @var ErrorController $errorController */
			$errorController = GeneralUtility::makeInstance(ErrorController::class);
			$response = $errorController->pageNotFoundAction(
				$GLOBALS['TYPO3_REQUEST'],
				'The requested page does not exist',
				['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
			);
			throw new ImmediateResponseException($response);
		}

		// find all tags
		$tagPid = $GLOBALS['TSFE']->id;
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$tags = $this->tagRepository->findTagsInRootLine($tagPid);
		} else {
			$tags = $this->tagRepository->findAll()->toArray();
		}

		// remember selection of the filter values, if any
		$selectedTag = NULL;
		if (isset($newsFilter['tag'])) {
			$selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']);
		}
		$selectedCategory = NULL;
		if(isset($newsFilter['category'])) {
			$selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']);
		}
		$this->view->assign('selectedCategory', $selectedCategory);
		$this->view->assign('selectedTag', $selectedTag);
		$this->view->assign('tags', $tags);
		$this->view->assign('categories', $categories);
		$this->view->assign('numberOfPages', $numberOfPages);
		$this->view->assign('newsItems', $newsByCategory);
		$this->view->assign('groupBy', 'category');
		$this->view->assign('allNews', $allNews);
		$this->view->assign('categoryTabs', TRUE);
	}

	/**
	 * Renders the news overview grouped by tags
	 *
	 * @param array $newsByTag
	 * @param array $allNews
	 * @param array $newsFilter
	 * @param int $currentPageBrowserPage
	 * @return void
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
	 * @throws ImmediateResponseException
	 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
	 */
	protected function overviewWithTags(
		array $newsByTag = [],
		array $allNews = [],
		array $newsFilter = [],
		int $currentPageBrowserPage = 0
	) {
		$startTime = (int) $this->settings['starttime'];
		$endTime = (int) $this->settings['endtime'];
		$newsLimitPerTag = (int) $this->settings['newsLimit'];
		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimitPerTag);
		$tagPid = (int) $this->settings['tagPid'];
		if (!$tagPid) {
			$tagPid = $GLOBALS['TSFE']->id;
		}

		$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
		$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
		$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);

		$categoryIds = NULL;
		if ($newsFilter['category']) {
			$categoryIds = [(int) $newsFilter['category']];
		}

		$this->tagRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]);
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$tags = $this->tagRepository->findTagsInRootLine($tagPid);
		} else {
			$tags = $this->tagRepository->findAll()->toArray();
		}

		$tagRestrictions = GeneralUtility::intExplode(',', $this->settings['tagRestrictions'], TRUE);
		if (count($tagRestrictions) > 0) {
			foreach ($tags as $key => $tag) {
				if (!in_array($tag->getUid(), $tagRestrictions, TRUE)) {
					unset($tags[$key]);
				}
			}
		}

		// Get news by tag id
		$tagIds = [];
		$tagsById = [];
		$categoriesById = [];
		$newsMetaData = [];
		foreach ($tags as $tag) {
			/** @var Tag $tag */
			$tagId = $tag->getUid();
			$tagIds[] = $tagId;
			$tagsById[$tagId] = $tag;

			$news = $this->newsRepository->findAllSortedNewsByCategories(
				$categoryIds,
				$newsLimitPerTag,
				$offset,
				$sortBy,
				[$tagId],
				$startTime,
				$endTime,
				$sortDirection
			);
			$newsMetaData[$tagId] = [];
			foreach ($news as $newsEntry) {
				/** @var News $newsEntry */
				$categoryId = $newsEntry->getPid();
				if (!isset($categoriesById[$categoryId])) {
					$categoriesById[$categoryId] = $this->categoryRepository->findByUid($categoryId);
				}
				$category = $categoriesById[$categoryId];
				if (!$category) {
					// Category isn't visible.
					continue;
				}

				$newsMetaData[$tagId][] = $this->getMetaDataForNews($newsEntry, $category);
			}
		}

		// Process news by tag id
		$maxNewsPerTag = 0;
		foreach ($tagsById as $tagId => $tag) {
			if (\count($newsMetaData[$tagId]) <= 0) {
				// Hide empty tags.
				continue;
			}

			if (isset($newsByTag[$tagId])) {
				$newsByTag[$tagId]['newsMetaData'] =
					\array_merge($newsByTag[$tagId]['newsMetaData'], $newsMetaData[$tagId]);
			} else {
				$newsByTag[$tagId] = [
					'record' => $tag,
					'recordId' => $tagId,
					'recordType' => 'tag',
					'newsMetaData' => $newsMetaData[$tagId],
					'newsCount' => \count($newsMetaData[$tagId])
				];
			}

			$maxNewsPerTag = \max($maxNewsPerTag, \count($newsByTag[$tagId]['newsMetaData']));
		}

		// Get all news by tags.
		if ($newsFilter['tag']) {
			$tagIds = [(int) $newsFilter['tag']];
		}
		$news = $this->newsRepository->findAllSortedNewsByCategories(
			$categoryIds,
			$newsLimitPerTag,
			$offset,
			$sortBy,
			$tagIds,
			$startTime,
			$endTime,
			$sortDirection
		);
		foreach ($news as $newsEntry) {
			/** @var News $newsEntry */
			$categoryId = $newsEntry->getPid();
			if (!isset($categoriesById[$categoryId])) {
				$categoriesById[$categoryId] = $this->categoryRepository->findByUid($categoryId);
			}
			/** @var Category $category */
			$category = $categoriesById[$categoryId];
			if (!$category) {
				// Category isn't visible.
				continue;
			}

			$allNews[] = $this->getMetaDataForNews($newsEntry, $category);
		}

		$this->highlightBestFitNews([], $tagIds);

		// Check to achieve less Ajax calls.
		$newsCount = $this->newsRepository->newsCountByCategories([], $tagIds, $startTime, $endTime);
		$numberOfPages = (int) ($newsLimitPerTag <= 0 ? 0 : ceil($newsCount / $newsLimitPerTag));
		if ($numberOfPages !== 0 && $currentPageBrowserPage >= $numberOfPages) {
			/** @var ErrorController $errorController */
			$errorController = GeneralUtility::makeInstance(ErrorController::class);
			$response = $errorController->pageNotFoundAction(
				$GLOBALS['TYPO3_REQUEST'],
				'The requested page does not exist',
				['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
			);
			throw new ImmediateResponseException($response);
		}

		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
		} else {
			$categories = $this->categoryRepository->findAll()->toArray();
		}

		// remember selection of the filter values, if any
		$selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']);
		$selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']);
		$this->view->assign('selectedCategory', $selectedCategory);
		$this->view->assign('selectedTag', $selectedTag);
		$this->view->assign('tags', $tags);
		$this->view->assign('categories', $categories);
		$this->view->assign('numberOfPages', $numberOfPages);
		$this->view->assign('newsItems', $newsByTag);
		$this->view->assign('groupBy', 'tag');
		$this->view->assign('allNews', $allNews);
		$this->view->assign('tagTabs', TRUE);
	}

	/**
	 * Initialize the overviewWithoutCategoriesAction to set the currentPageBrowserPage parameter
	 *
	 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
	 */
	public function initializeOverviewWithoutCategoriesAction() {
		$currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'];
		if ($currentPageBrowserPage > 0) {
			$this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage);
		}
	}

	/**
	 * Renders the news in a paginated list
	 *
	 * @param array $newsMetaData
	 * @param array|null $newsFilter
	 * @param int $currentPageBrowserPage
	 * @return null|\Psr\Http\Message\ResponseInterface
	 * @throws ImmediateResponseException
	 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 */
	protected function overviewWithoutCategoriesAction(
		array $newsMetaData = [],
		array $newsFilter = NULL,
		int $currentPageBrowserPage = 0
	): ?\Psr\Http\Message\ResponseInterface {
		// remember selection of the filter values, if any
		$selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']);
		$selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']);
		$this->view->assign('selectedTag', $selectedTag);
		$this->view->assign('selectedCategory', $selectedCategory);

		$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
		$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
		$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);

		$newsPerPage = (int) $this->settings['newsLimit'];
		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsPerPage);

		$newsCount = 0;
		$categoryIds = NULL;
		$categoriesById = [];
		$startTime = (int) $this->settings['starttime'];
		$endTime = (int) $this->settings['endtime'];
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
			if (count($categories) > 0) {
				$categoryIds = [];
				/** @var QueryResult $categories */
				foreach ($categories as $category) {
					/** @var Category $category */
					$categoriesById[$category->getUid()] = $category;
					$categoryIds[] = $category->getUid();
					if ($category->_getProperty('_languageUid') > 0) {
						$originalLangCategory = $this->categoryRepository->findOriginalLanguageById(
							$category->getUid()
						);
						if ($originalLangCategory) {
							$categoryIds[] = $originalLangCategory->getUid();
							$categoriesById[$originalLangCategory->getUid()] = $originalLangCategory;
						}
					}
				}

				// filter by category and tag if selected in the filter
				if ($newsFilter['category']) {
					$categoryIds = [(int) $newsFilter['category']];
				}

				$tagIds = NULL;
				if ($newsFilter['tag']) {
					$tagIds = [(int) $newsFilter['tag']];
				}

				$newsCount = $this->newsRepository->newsCountByCategories($categoryIds, $tagIds, $startTime, $endTime);
			}
		} else {
			$newsCount = $this->newsRepository->countAll($startTime, $endTime);
			$categories = $this->categoryRepository->findAll()->toArray();
			foreach ($categories as $category) {
				/** @var Category $category */
				$categoriesById[$category->getUid()] = $category;
			}
		}

		if ($newsCount <= 0) {
			if (version_compare(
				\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<'
			)) {
				return NULL;
			} else {
				return $this->htmlResponse();
			}
		}

		// filter by category and tag if selected in the filter
		if ($newsFilter['category']) {
			$categoryIds = [(int) $newsFilter['category']];
		}

		$tagIds = NULL;
		if ($newsFilter['tag']) {
			$tagIds = [(int) $newsFilter['tag']];
		}

		$news = $this->newsRepository->findAllSortedNewsByCategories(
			$categoryIds,
			$newsPerPage,
			$offset,
			$sortBy,
			$tagIds,
			$startTime,
			$endTime,
			$sortDirection
		);
		foreach ($news as $newsEntry) {
			/** @var News $newsEntry */
			$data = $this->getMetaDataForNews($newsEntry, $categoriesById[$newsEntry->getPid()]);
			$newsMetaData[] = $data;
		}

		$this->highlightBestFitNews($categoryIds);
		$numberOfPages = (int) ($newsPerPage <= 0 ? 0 : ceil($newsCount / $newsPerPage));
		if ($numberOfPages !== 0 && $currentPageBrowserPage >= $numberOfPages) {
			/** @var ErrorController $errorController */
			$errorController = GeneralUtility::makeInstance(ErrorController::class);
			$response = $errorController->pageNotFoundAction(
				$GLOBALS['TYPO3_REQUEST'],
				'The requested page does not exist',
				['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
			);
			throw new ImmediateResponseException($response);
		}

		// find all tags
		$currentPageId = $GLOBALS['TSFE']->id;
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			$tags = $this->tagRepository->findTagsInRootLine($currentPageId);
		} else {
			$tags = $this->tagRepository->findAll()->toArray();
		}

		$this->view->assign('tags', $tags);
		$this->view->assign('categories', $categories);
		$this->view->assign('numberOfPages', $numberOfPages);
		$this->view->assign('newsMetaData', $newsMetaData);
		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
			return NULL;
		} else {
			return $this->htmlResponse();
		}
	}

	/**
	 * Sets the pagebrowser page to the given new page.
	 *
	 * @param int $newPage
	 * @return void
	 */
	protected function setPageBrowserPage($newPage) {
		$_GET['tx_sgnews_pagebrowser']['currentPage'] = $newPage;
	}
}