<?php

namespace SGalinski\SgJobs\Service;

/***************************************************************
 *  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 TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Request;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;

/**
 * Backend Service class
 */
class BackendService {

	/**
	 * Get all pages the be user has access to
	 *
	 * @return array
	 * @throws \InvalidArgumentException
	 */
	public static function getPages(): array {
		$out = [];
		/** @var $databaseConnection DatabaseConnection */
		$databaseConnection = $GLOBALS['TYPO3_DB'];
		$rows = $databaseConnection->exec_SELECTgetRows(
			'*',
			'pages',
			'deleted = 0 AND is_siteroot = 1'
		);

		foreach ($rows as $row) {
			$pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
			if ($pageInfo) {
				$rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', TRUE);
				ksort($rootline);
				$path = '/root';
				foreach ($rootline as $page) {
					$path .= '/p' . dechex($page['uid']);
				}
				$pageInfo['path'] = $path;
				$out[] = $pageInfo;
			}
		}
		return $out;
	}

	/**
	 * create buttons for the backend module header
	 *
	 * @param DocHeaderComponent $docHeaderComponent
	 * @param Request $request
	 * @throws \InvalidArgumentException
	 * @throws \UnexpectedValueException
	 */
	public static function makeButtons($docHeaderComponent, $request) {
		/** @var ButtonBar $buttonBar */
		$buttonBar = $docHeaderComponent->getButtonBar();

		/** @var IconFactory $iconFactory */
		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);

		// Refresh
		$refreshButton = $buttonBar->makeLinkButton()
			->setHref(GeneralUtility::getIndpEnv('REQUEST_URI'))
			->setTitle(LocalizationUtility::translate('LLL:EXT:lang/locallang_core.xlf:labels.reload', ''))
			->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
		$buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT);

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

		$buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
		$docHeaderComponent->getButtonBar();
	}

	/**
	 * Retrieves the next site root in the page hierarchy from the current page
	 *
	 * @param int $currentPid
	 * @return int
	 */
	public static function getSiteRoot($currentPid): int {
		$rootLine = BackendUtility::BEgetRootLine((int) $currentPid);
		$siteRoot = ['uid' => 0];

		foreach ($rootLine as $page) {
			if ((int) $page['is_siteroot'] === 1) {
				$siteRoot = $page;
				break;
			}
		}

		return $siteRoot['uid'];
	}

	/**
	 * Returns the root uid based on the given page uid
	 *
	 * @param int $pageUid
	 * @return int
	 */
	public static function getRootUidByPageUid($pageUid): int {
		$out = 0;
		$pageRootline = BackendUtility::BEgetRootLine($pageUid);
		foreach ($pageRootline as $pageData) {
			if ($pageData['is_siteroot']) {
				$out = (int) $pageData['uid'];
				break;
			}
		}
		return $out;
	}

	/**
	 * Get the root pages
	 *
	 * @return array
	 */
	public static function getRootOptions(): array {
		$rootOptionRows = (array) BackendUtility::getRecordsByField('pages', 'is_siteroot', 1, '', '', 'sorting');
		$rootOptions = [];
		foreach ($rootOptionRows as $row) {
			$pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
			if ($pageInfo) {
				$rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', TRUE);
				ksort($rootline);
				$path = '/root';
				foreach ($rootline as $page) {
					$path .= '/p' . dechex($page['uid']);
				}
				$pageInfo['path'] = $path;
				$pageInfo['_thePathFull'] = substr($pageInfo['_thePathFull'], 1);
				$pageInfo['_thePathFull'] = substr($pageInfo['_thePathFull'], 0, -1);
				$rootOptions[] = $pageInfo;
			}
		}

		return $rootOptions;
	}

	/**
	 * Returns the uids of the pages with job records
	 *
	 * @return array
	 * @throws \InvalidArgumentException
	 */
	public static function getPagesWithJobRecords(): array {
		$out = [];
		/** @var $databaseConnection DatabaseConnection */
		$databaseConnection = $GLOBALS['TYPO3_DB'];
		$rows = $databaseConnection->exec_SELECTgetRows(
			'DISTINCT pid',
			'tx_sgjobs_domain_model_job',
			'deleted = 0'
		);
		foreach ($rows as $row) {
			$pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
			if ($pageInfo) {
				$rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', TRUE);
				ksort($rootline);
				$path = '/root';
				foreach ($rootline as $page) {
					$path .= '/p' . dechex($page['uid']);
				}
				$pageInfo['path'] = $path;
				$out[] = $pageInfo;
			}
		}
		return $out;
	}

	/**
	 * Counts the job records on the specified page and returns users records based on the filter options
	 *
	 * @param int $pid
	 * @param array $filters
	 * @return array
	 * @throws \InvalidArgumentException
	 */
	public static function getJobsByPid($pid, array $filters = []): array {
		$pid = (int) $pid;
		$tableName = 'fe_users';
		/** @var $databaseConnection DatabaseConnection */
		$databaseConnection = $GLOBALS['TYPO3_DB'];
		/** @var DatabaseRecordList $databaseRecordList */
		$databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class);

		$databaseRecordList->start($pid, $tableName, 0);
		$databaseRecordList->setTotalItems($tableName, $pid, []);
		$totalUserCount = (int) $databaseRecordList->totalItems;
		if (trim($filters['search'])) {
			$databaseRecordList->start($pid, $tableName, 0, trim($filters['search']));
		}
		$queryBuilder = $databaseRecordList->getQueryBuilder($tableName, $pid);
		if ($filters['usergroups'] && count($filters['usergroups'])) {
			$expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
				->getConnectionForTable($tableName)
				->getExpressionBuilder();
			$groupConstraints = [];
			/** @var array $usergroups */
			$usergroups = $filters['usergroups'];
			foreach ($usergroups as $groupUid) {
				$groupUid = (int) $groupUid;
				if ($groupUid) {
					$groupConstraints[] = $expressionBuilder->inSet($tableName . '.usergroup', $groupUid);
				}
			}
			if (count($groupConstraints)) {
				$groupConstraint = call_user_func_array([$expressionBuilder, 'orX'], $groupConstraints);
				$queryBuilder = $databaseRecordList->getQueryBuilder($tableName, $pid, [$groupConstraint]);
			}
		}
		$users = $queryBuilder->execute()->fetchAll();

		return [$totalUserCount, $users];
	}
}