<?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\Paginator\QueryBuilderPaginator;
use SGalinski\SgNews\Utility\BackendNewsUtility;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Pagination\SimplePagination;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

/**
 * News Controller
 */
class BackendController extends ActionController {
	/**
	 * The uid of the current page
	 *
	 * @var int
	 */
	private $pageUid = 0;

	/**
	 * The info fields of the current page
	 *
	 * @var array
	 */
	private $pageInfo = [];

	/**
	 * The uid of the current root page
	 *
	 * @var int
	 */
	private $rootPageUid = 0;

	/**
	 * Currently selected language
	 *
	 * @var int
	 */
	public $language;

	/**
	 * DocHeaderComponent
	 *
	 * @var DocHeaderComponent
	 */
	private $docHeaderComponent;


	/**
	 * @var ?ModuleTemplate
	 */
	protected $moduleTemplate = NULL;

	/**
	 * Initializes the view before invoking an action method.
	 *
	 * Override this method to solve assign variables common for all actions
	 * or prepare the view in another way before the action is called.
	 *
	 * @param ViewInterface $view The view to be initialized
	 *
	 * @return void
	 * @throws \UnexpectedValueException
	 * @throws \InvalidArgumentException
	 * @api
	 */
	protected function initializeView(ViewInterface $view) {
		$GLOBALS['LANG']->includeLLFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
		// create doc header component
		$this->pageUid = (int) GeneralUtility::_GP('id');
		/** @var BackendUserAuthentication $backendUser */
		$backendUser = $GLOBALS['BE_USER'];
		$this->pageInfo = BackendUtility::readPageAccess($this->pageUid, $backendUser->getPagePermsClause(1));
		if ($this->pageInfo) {
			if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
				$this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class);
			} else {
				$this->getDocHeaderComponent();
			}
			if ($this->pageUid) {
				$this->rootPageUid = BackendNewsUtility::getRootUidByPageUid($this->pageUid);
			}

			/** @var BackendUserAuthentication $backendUser */
			$backendUser = $GLOBALS['BE_USER'];

			$menuSettings = GeneralUtility::_GP('SET') ?: [];
			foreach ($menuSettings as $key => $menuSetting) {
				$backendUser->pushModuleData('tools_beuser/index.php/web_SgNewsNews_' . $key, $menuSetting);
			}

			$this->language = $backendUser->getModuleData(
				'tools_beuser/index.php/web_SgNewsNews_language',
				'ses'
			) ?: 0;
			$languageOptions = BackendNewsUtility::getAvailableLanguages($this->pageUid);
			$currentLanguageInfo = $languageOptions[$this->language] ?? NULL;

			$this->docHeaderComponent->setMetaInformation($this->pageInfo);
			$this->makeButtons();
			$this->makeLanguageMenu();
			$this->view->assign('pageUid', $this->pageUid);
			$this->view->assign('rootPageUid', $this->rootPageUid);
			$this->view->assign('language', $this->language);
			$this->view->assign('languageInfo', $currentLanguageInfo);
			$this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent());
		}
	}

	/**
	 * @param array|null $filters
	 * @return \Psr\Http\Message\ResponseInterface|null
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 */
	public function indexAction(array $filters = NULL): ?\Psr\Http\Message\ResponseInterface {
		$showNewsList = FALSE;
		if (
			($this->pageUid && $this->pageUid === $this->rootPageUid) ||
			(isset($this->pageInfo['doktype']) && (int) $this->pageInfo['doktype'] === BackendNewsUtility::CATEGORY_DOKTYPE)
		) {
			/** @var BackendUserAuthentication $backendUser */
			$backendUser = $GLOBALS['BE_USER'];
			if ($filters === NULL) {
				$filters = $backendUser->getModuleData('tools_beuser/index.php/web_SgNewsNews_filters', 'ses') ?: [];
			} else {
				$backendUser->pushModuleData('tools_beuser/index.php/web_SgNewsNews_filters', $filters);
			}
			if ((int) $this->pageInfo['doktype'] !== BackendNewsUtility::CATEGORY_DOKTYPE) {
				$categories = BackendNewsUtility::getCategoriesForSiteRoot($this->rootPageUid);
				$this->view->assign('categories', $categories);
				$this->view->assign('showCategoryFilter', TRUE);
			} else {
				$filters['categories'] = [$this->pageUid];
			}
			$tags = BackendNewsUtility::getTagsForPage($this->pageUid, $this->language);
			[$news, $newsQueryBuilder] = BackendNewsUtility::getNewsByFilters($this->rootPageUid, $filters, $this->language);

			$paginator = new QueryBuilderPaginator($newsQueryBuilder);
			$pagination = new SimplePagination($paginator);

			$this->view->assign('paginator', $paginator);
			$this->view->assign('pagination', $pagination);

			$this->view->assign('tags', $tags);
			$this->view->assign('news', $news);
			$this->view->assign('filters', $filters);
			$showNewsList = TRUE;
		} else {
			$alternativePageOptions = BackendNewsUtility::getAlternativePageOptions();
			$this->view->assign('alternativePageOptions', $alternativePageOptions);
		}
		$this->view->assign('showNewsList', $showNewsList);

		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
			$this->view->assign('V11', FALSE);
			return NULL;
		} else {
			$this->view->assign('V11', TRUE);
			return $this->createBackendResponse();
		}
	}

	/**
	 * create buttons for the backend module header
	 *
	 * @return void
	 * @throws \InvalidArgumentException
	 * @throws \UnexpectedValueException
	 */
	private function makeButtons() {
		/** @var ButtonBar $buttonBar */
		$buttonBar = $this->docHeaderComponent->getButtonBar();

		/** @var IconFactory $iconFactory */
		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
		$locallangPath = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:';

		// Refresh
		$refreshButton = $buttonBar->makeLinkButton()
			->setHref(GeneralUtility::getIndpEnv('REQUEST_URI'))
			->setTitle(
				LocalizationUtility::translate(
					$locallangPath . 'labels.reload'
				)
			)
			->setIcon($iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL));
		$buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT);

		// shortcut button
		$shortcutButton = $buttonBar->makeShortcutButton()
			->setModuleName($this->request->getPluginName())
			->setGetVariables(
				[
					'id',
					'M'
				]
			)
			->setSetVariables([]);
		$buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
	}

	/**
	 * create buttons for the backend module header
	 *
	 * @return void
	 * @throws \InvalidArgumentException
	 */
	private function makeLanguageMenu() {
		$languageMenu = $this->docHeaderComponent->getMenuRegistry()->makeMenu();
		$languageMenu->setIdentifier('languageMenu');
		$languages = BackendNewsUtility::getAvailableLanguages($this->pageUid);
		$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
		foreach ($languages as $key => $language) {
			$menuItem = $languageMenu
				->makeMenuItem()
				->setTitle($language['title'])
				->setHref(
					$uriBuilder->buildUriFromRoute(
						'web_SgNewsNews',
						['id' => $this->pageUid, 'SET' => ['language' => $key]]
					)
				);
			if ((int) $this->language === (int) $key) {
				$menuItem->setActive(TRUE);
			}
			$languageMenu->addMenuItem($menuItem);
		}
		$this->docHeaderComponent->getMenuRegistry()->addMenu($languageMenu);
	}


	/**
	 * Use the ModuleTemplateResponse to create a response object for the backend
	 *
	 * @return  \Psr\Http\Message\ResponseInterface
	 */
	protected function createBackendResponse(): \Psr\Http\Message\ResponseInterface {
		return $this->htmlResponse($this->view->render());
	}

	/**
	 * Since we cannot use constructer Injection, we do have to get one Dynamicly. If we want to use
	 * our ModuleTemplate, call GetModuleTemplate before, which will init one if there is none for some reason
	 */
	protected function getModuleTemplate() {
		if ($this->moduleTemplate === NULL) {
			$moduleTemplateFactory = GeneralUtility::makeInstance(
				\TYPO3\CMS\Backend\Template\ModuleTemplateFactory::class
			);
			$this->moduleTemplate = $moduleTemplateFactory->create($this->request);
		}
	}

	/**
	 * Other Helper function, which gets us just the DocHeaderComponent
	 */
	protected function getDocHeaderComponent() {
		if ($this->moduleTemplate === NULL) {
			$this->getModuleTemplate();
		}
		$this->docHeaderComponent = $this->moduleTemplate->getDocHeaderComponent();
	}
}