<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 4/8/17
 * Time: 6:53 PM
 */

namespace IMATHUZH\Qfq\Core\Store;


use IMATHUZH\OidcClient\Service\UserStorage;
use IMATHUZH\Qfq\Core\Exception\Thrower;
use IMATHUZH\Qfq\Core\Helper\Path;
use IMATHUZH\Qfq\Core\Typo3\T3Handler;


/**
 * Class T3Info
 * @package qfq
 */
class T3Info {

    /**
     * Collect some global T3 variables and return them as array.
     *
     * @return array
     *
     * @todo v12 migration: access feUser via $request->getAttribute('frontend.user')
     */
    public static function getVars() {

        $t3vars = array();

        $t3vars[TYPO3_FE_USER] = isset($GLOBALS["TSFE"]->fe_user->user["username"]) ? $GLOBALS["TSFE"]->fe_user->user["username"] : '';
        $t3vars[TYPO3_FE_USER_EMAIL] = isset($GLOBALS["TSFE"]->fe_user->user["email"]) ? $GLOBALS["TSFE"]->fe_user->user["email"] : '';

        $t3vars[TYPO3_FE_USER_UID] = isset($GLOBALS["TSFE"]->fe_user->user["uid"]) ? $GLOBALS["TSFE"]->fe_user->user["uid"] : '';

        $t3vars[TYPO3_FE_USER_GROUP] = isset($GLOBALS["TSFE"]->fe_user->user["usergroup"]) ? $GLOBALS["TSFE"]->fe_user->user["usergroup"] : '';

        // Will be set later
        $t3vars[TYPO3_TT_CONTENT_UID] = 'not set yet';

        $t3vars[TYPO3_PAGE_ID] = isset($GLOBALS["TSFE"]->id) ? $GLOBALS["TSFE"]->id : '';

        $t3vars[TYPO3_PAGE_ALIAS] = empty($GLOBALS["TSFE"]->page["alias"]) ? $t3vars[TYPO3_PAGE_ID] : $GLOBALS["TSFE"]->page["alias"];

        if (T3Handler::useSlugsInsteadOfPageAlias()) {
            $t3vars[TYPO3_PAGE_SLUG] = empty($GLOBALS["TSFE"]->page["slug"]) ? '/' : $GLOBALS["TSFE"]->page["slug"];
        } else {
            $t3vars[TYPO3_PAGE_SLUG] = $t3vars[TYPO3_PAGE_ALIAS]; // the Form Editor report (formEditor.qfqr) depends on this for T3 older than version 9.
        }

        $t3vars[TYPO3_PAGE_TITLE] = isset($GLOBALS["TSFE"]->page["title"]) ? $GLOBALS["TSFE"]->page["title"] : '';

        $t3vars[TYPO3_PAGE_TYPE] = isset($GLOBALS["TSFE"]->type) ? $GLOBALS["TSFE"]->type : '';

        $t3vars[TYPO3_PAGE_LANGUAGE] = self::getLanguageId();

        $t3vars[TYPO3_PAGE_LANGUAGE_PATH] = self::getLanguagePath($t3vars[TYPO3_PAGE_LANGUAGE]);

        $t3vars[TYPO3_BE_USER_LOGGED_IN] = self::beUserLoggedIn() ? 'yes' : 'no';

        $t3vars[TYPO3_BE_USER] = isset($GLOBALS["BE_USER"]->user["username"]) ? $GLOBALS["BE_USER"]->user["username"] : '';
        $t3vars[TYPO3_BE_USER_EMAIL] = isset($GLOBALS["BE_USER"]->user["email"]) ? $GLOBALS["BE_USER"]->user["email"] : '';
        $t3vars[TYPO3_BE_USER_UID] = isset($GLOBALS["BE_USER"]->user["uid"]) ? $GLOBALS["BE_USER"]->user["uid"] : '';

        $t3vars[TYPO3_PAGE_DESCRIPTION] = $GLOBALS["TSFE"]->page[T3DATA_DESCRIPTION] ?? '';

        $t3vars[TYPO3_PAGE_ABSTRACT] = $GLOBALS["TSFE"]->page[T3DATA_ABSTRACT] ?? '';

        $t3vars[TYPO3_PAGE_KEYWORDS] = $GLOBALS["TSFE"]->page[T3DATA_KEYWORDS] ?? '';

        if (defined('TYPO3_version')) {
            $t3vars[TYPO3_VERSION] = TYPO3_version;
        }

        /***** oidc data ******/

        if (class_exists(UserStorage::class)) {
            $oidcStorage = (new UserStorage($GLOBALS["TSFE"]->fe_user))->get() ?? [];
        } else {
            $oidcStorage = [];
        }

        $t3vars[TYPO3_OIDC_PROVIDER] = $oidcStorage['provider'] ?? '';
        $t3vars[TYPO3_OIDC_RESOURCE_ID] = $oidcStorage['resource_id'] ?? '';
        $t3vars[TYPO3_OIDC_SUB] = $oidcStorage['sub'] ?? '';
        $t3vars[TYPO3_OIDC_EMAIL] = $oidcStorage['email'] ?? '';
        if (isset($oidcStorage['email_verified'])) {
            $t3vars[TYPO3_OIDC_EMAIL_VERIFIED] = ($oidcStorage['email_verified'] === true) ? 'true' : 'false';
        } else {
            $t3vars[TYPO3_OIDC_EMAIL_VERIFIED] = 'null';
        }
        $t3vars[TYPO3_OIDC_GIVEN_NAME] = $oidcStorage['given_name'] ?? '';
        $t3vars[TYPO3_OIDC_FAMILY_NAME] = $oidcStorage['family_name'] ?? '';

        /***** oidc data end ******/


        return $t3vars;
    }

    /**
     * Returns the page language uid. This is only possible if QFQ is called via T3, not via API.
     *
     * @return string
     */
    public static function getLanguageId() {
        if (class_exists('TYPO3\CMS\Core\Context\Context')) {
            // Typo3 version >=9
            $context = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class);
            $languageAspect = $context->getAspect('language');
            // (previously known as TSFE->sys_language_uid)
            return $languageAspect->getId();
        } elseif (isset($GLOBALS["TSFE"]->sys_language_uid)) {
            // Typo3 version <=8
            return $GLOBALS["TSFE"]->sys_language_uid;
        }
        return '';
    }

    /**
     * Returns the base url with language path. This is only possible if QFQ is called via T3, not via API.
     *
     * @return string
     * @throws \UserReportException
     */
    public static function getBaseUrlLang() {
        if (!T3Handler::isTypo3Loaded()) {
            return null;
        }

        $lid = self::getLanguageId();
        if ($lid !== '' && is_numeric($lid) && T3Handler::typo3VersionGreaterEqual9()) {
            $lid = intval($lid);
            try {
                // In an API call Typo3 might have been loaded manually by QFQ at some earlier point. But the following line does not work in that case.
                $sf = new \TYPO3\CMS\Core\Site\SiteFinder();
            } catch (\Throwable $e) {
                return null;
            }
            $allSites = $sf->getAllSites();
            if (count($allSites) < 1) {
                return null;
            } else {
                $site = self::getSiteConfiguration($sf);
                $lang = $site->getLanguageById($lid);
                $base = $lang->getBase();
                return (string)$base;
            }
        }
        return null;
    }

    /**
     * Check if there is a Typo3 beUser is logged in. This is only possible if QFQ is called via T3, not via API
     *
     * @return bool  true: current Browser session is a logged in BE User.
     */
    public static function beUserLoggedIn() {

        if (T3Handler::isTypo3Loaded() && T3Handler::typo3VersionGreaterEqual9()) {
            // Typo3 version >=9
            $context = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class);
            return $context->getPropertyFromAspect('backend.user', 'isLoggedIn');
        } elseif (!empty($GLOBALS["TSFE"]->beUserLogin) && $GLOBALS["TSFE"]->beUserLogin === true) {
            // Typo3 version <=8
            return true;
        }
        return false;
    }

    /**
     * Returns the language path part. Helpful for forwardPage handling of forms in T3 >=V10
     *
     * @return string
     */
    public static function getLanguagePath($languageId): string {
        $languagePath = '';
        if (T3Handler::typo3VersionGreaterEqual10() && isset($GLOBALS['TYPO3_REQUEST'])) {
            $siteIdentifier = $GLOBALS['TYPO3_REQUEST']->getAttribute('site')->getIdentifier();
            $siteConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Site\SiteFinder::class)->getSiteByIdentifier($siteIdentifier)->getConfiguration();
            $languages = $siteConfiguration['languages'];
            $actualLanguage = $languages[$languageId]['base'];
            $languagePath = trim($actualLanguage, '/');
        }

        return $languagePath;
    }

    /**
     * Returns the site configuration from current page. Used for T3 >=V10.
     *
     * object $sf
     * @return object
     */
    public static function getSiteConfiguration($sf): object {
        if (T3Handler::typo3VersionGreaterEqual10() && isset($GLOBALS['TYPO3_REQUEST'])) {
            $siteIdentifier = $GLOBALS['TYPO3_REQUEST']->getAttribute('site')->getIdentifier();
            $actualSite = $sf->getSiteByIdentifier($siteIdentifier);
        } else {
            $allSites = $sf->getAllSites();
            $actualSite = reset($allSites);
        }

        return $actualSite;
    }

    /**
     * Get typo 3 extension informations
     *
     *
     * @return array
     */
    public static function getAllExtensionsInfo(): array {
        $packageStatesPath = Path::absoluteTypo3Conf('PackageStates.php');

        if (!file_exists($packageStatesPath)) {
            throw new \Exception('PackageStates.php does not exist at the specified path.');
        }

        $packageStates = include $packageStatesPath;

        $extensions = [];
        if (isset($packageStates['packages'])) {
            foreach ($packageStates['packages'] as $key => $package) {
                $extensions[$key] = $package['packagePath'];
            }
        }

        return $extensions;
    }
}