<?php
namespace intec\template\controllers;

use intec\core\db\ActiveRecord;
use intec\core\handling\controllers\Controller;

/**
 * Класс, представляющий базовую страницу.
 * Class BasePage
 * @package intec\template\controllers
 * @author apocalypsisdimon@gmail.com
 */
abstract class BaseController extends Controller
{
    /**
     * Линейка Intec Kosmos и связанные модули подключаются целиком по префиксу
     * @var list<string>
     */
    protected static array $allowedNamespacePrefixes = [
        'intec.kosmos:',
        'intec.seo:',
        'intec.regionality:',
        'intec:startshop.',
    ];

    /**
     * Имена после normalizeComponentName() (нижний регистр, без пробелов)
     * @var list<string>
     */
    protected static array $allowedBitrixComponents = [
        'bitrix:search.title',
        'bitrix:main.include',
        'bitrix:catalog.product.subscribe',
        'bitrix:form.result.new',
        'bitrix:catalog.element',
        'bitrix:system.auth.form'
    ];

    /**
     * Состояние захвата выходных данных.
     * @var boolean
     */
    protected $_isCaptureOutput = false;

    /**
     * @inheritdoc
     */
    public function beforeAction($action, $parameters)
    {
        ActiveRecord::disableCache();

        return parent::beforeAction($action, $parameters);
    }

    /**
     * Заканчивает захват выходных данных и возвращает буферизированные данные.
     * @return string|null
     */
    public function endOutputCapture()
    {
        if (!$this->_isCaptureOutput)
            return null;

        $content = ob_get_contents();

        ob_end_clean();

        $this->_isCaptureOutput = false;

        return $content;
    }

    /**
     * Возвращает состояние захвата выходных данных.
     * @return boolean
     */
    public function getIsCaptureOutput()
    {
        return $this->_isCaptureOutput;
    }

    /**
     * Начинает захват выходных данных.
     */
    public function startOutputCapture()
    {
        if ($this->_isCaptureOutput)
            return;

        $this->_isCaptureOutput = true;

        ob_start();
    }

    /**
     * @param mixed $name
     * @return string
     */
    protected static function normalizeComponentName(mixed $name): string
    {
        $name = mb_strtolower(trim((string)$name));

        return str_replace(
            search: ' ',
            replace: '',
            subject: $name
        );
    }

    /**
     * @param mixed $name
     * @return bool
     */
    protected static function isAllowedComponent(mixed $name): bool
    {
        $normalized = static::normalizeComponentName($name);

        if ($normalized === '')
            return false;

        foreach (static::$allowedNamespacePrefixes as $prefix) {
            $len = strlen($prefix);
            $isAllowed = static::isEqualStrings(
                string1: $normalized,
                string2: $prefix,
                length: $len
            );

            if ($len > 0 && $isAllowed && strlen($normalized) > $len)
                return true;
        }

        if (!static::isEqualStrings(string1: $normalized, string2: 'bitrix:', length: 7))
            return false;

        return in_array(
            needle: $normalized,
            haystack: static::$allowedBitrixComponents,
            strict: true
        );
    }

    /**
     * @param string $string1
     * @param string $string2
     * @param int $length
     * @return bool
     */
    protected static function isEqualStrings(string $string1, string $string2, int $length): bool
    {
        return strncmp(
                string1: $string1,
                string2: $string2,
                length: $length
            ) === 0;
    }
}
