<?php
/**
 * @package         ReReplacer
 * @version         14.4.1
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            https://regularlabs.com
 * @copyright       Copyright © 2025 Regular Labs All Rights Reserved
 * @license         GNU General Public License version 2 or later
 */

namespace RegularLabs\Plugin\System\ReReplacer;

defined('_JEXEC') or die;

use Joomla\CMS\Factory as JFactory;
use RegularLabs\Library\Cache as RL_Cache;
use RegularLabs\Library\Parameters as RL_Parameters;
use RegularLabs\Library\PluginTag as RL_PluginTag;
use RegularLabs\Library\RegEx as RL_RegEx;

class Params
{
    protected static $current_article_id = 0;

    static public function get($overrides = null)
    {
        $cache = new RL_Cache(__METHOD__);

        if ($cache->exists())
        {
            return RL_Parameters::overrideFromObject($cache->get(), $overrides);
        }

        $params = RL_Parameters::getPlugin('rereplacer');

        $params->article_tag = RL_PluginTag::clean($params->article_tag);
//

        [$params->tag_character_data_start, $params->tag_character_data_end]
            = explode('.', $params->tag_characters_data);

        [$params->tag_character_start, $params->tag_character_end]
            = explode('.', $params->tag_characters);

        $cache->set($params);

        return RL_Parameters::overrideFromObject($params, $overrides);
    }

    static public function getAlignment()
    {
        $params = self::get();


        if ( ! $params->alignment)
        {
            $params->alignment = JFactory::getApplication()->getLanguage()->isRTL() ? 'right' : 'left';
        }

        return 'align_' . $params->alignment;
    }

    public static function getAuthorisedViewLevels()
    {
        $cache = new RL_Cache;

        if ($cache->exists())
        {
            return $cache->get();
        }

        $view_levels = JFactory::getUser()->getAuthorisedViewLevels();
        $view_levels = array_unique($view_levels);

        if (empty($view_levels))
        {
            $view_levels = [0];
        }

        return $cache->set($view_levels);
    }

    static public function getCurrentArticleId()
    {
        return static::$current_article_id;
    }

    static public function getDataTagCharacters()
    {
        $params = self::get();

        return [$params->tag_character_data_start, $params->tag_character_data_end];
    }

    static public function getDatabase($name)
    {
        $databases = self::get()->databases;

        foreach ($databases as $database)
        {
            if ($database->name == $name)
            {
                return $database;
            }
        }

        return null;
    }

    static public function getIfEndTag()
    {
        [$tag_start, $tag_end] = self::getTagCharacters();

        return $tag_start . '/if' . $tag_end;
    }

    static public function getPositioning()
    {
        return 'top';
    }

    static public function getRegex($type = 'tag')
    {
        $regexes = self::getRegexes();

        return $regexes->{$type} ?? $regexes->tag;
    }

    static public function getTagCharacters()
    {
        $params = self::get();

        return [$params->tag_character_start, $params->tag_character_end];
    }

    static public function getTagNames()
    {
        $params = self::get();

        return
            [
                $params->article_tag,
            ];
    }

    static public function setCurrentArticle($article)
    {
        static::$current_article_id = $article->id ?? 0;
    }

    private static function getDataTagRegex($article_selector = '')
    {
        [$tag_start, $tag_end] = self::getDataTagCharacters();

        $inside_tag = RL_PluginTag::getRegexInsideTag($tag_start, $tag_end);
        $spaces     = RL_PluginTag::getRegexSpaces();

        $tag_start = RL_RegEx::quote($tag_start);
        $tag_end   = RL_RegEx::quote($tag_end);

        $article_selector = $article_selector
            ? RL_RegEx::quote($article_selector, 'article_selector') . '\:'
            : '(?:(?<article_selector>(?:[0-9]+|previous|next|first|last))\:)?';

        $data_group = '(?:' . RL_RegEx::quote(DataHelper::getDataGroupPrefixes(), 'data_group') . '[\:-])?';

        $data_key = '(?<data_key>[a-z0-9-_]+)';

        return $tag_start . '(?<is_closing_tag>/)?'
            . $article_selector
            . '(?<full_key>' . $data_group . $data_key . ')'
            . '(?:' . $spaces . '(?<attributes>' . $inside_tag . '))?'
            . $tag_end;
    }

    private static function getIfStatementRegex()
    {
        [$tag_start, $tag_end] = self::getTagCharacters();

        $inside_tag = RL_PluginTag::getRegexInsideTag($tag_start, $tag_end);
        $spaces     = RL_PluginTag::getRegexSpaces();

        $tag_start = RL_RegEx::quote($tag_start);
        $tag_end   = RL_RegEx::quote($tag_end);

        return $tag_start . 'if' . $spaces . $inside_tag . $tag_end
            . '.*?'
            . $tag_start . '/if' . $tag_end;
    }

    private static function getIfTagRegex()
    {
        [$tag_start, $tag_end] = self::getTagCharacters();

        $inside_tag = RL_PluginTag::getRegexInsideTag($tag_start, $tag_end);
        $spaces     = RL_PluginTag::getRegexSpaces();

        $tag_start = RL_RegEx::quote($tag_start);
        $tag_end   = RL_RegEx::quote($tag_end);

        return $tag_start
            . '(?<type>if|else ?if|else)(?:' . $spaces . '(?<condition>' . $inside_tag . '))?'
            . $tag_end;
    }

    private static function getPluginTagRegex()
    {
        [$tag_start, $tag_end] = Params::getTagCharacters();

        $pre        = RL_PluginTag::getRegexSurroundingTagsPre();
        $post       = RL_PluginTag::getRegexSurroundingTagsPost();
        $inside_tag = RL_PluginTag::getRegexInsideTag($tag_start, $tag_end);
        $spaces     = RL_PluginTag::getRegexSpaces();

        $tag_start = RL_RegEx::quote($tag_start);
        $tag_end   = RL_RegEx::quote($tag_end);

        $tags   = RL_RegEx::quote(self::getTagNames(), 'tag');
        $set_id = '(?:-[a-zA-Z0-9-_]+)?';

        return '(?<opening_tags_before_open>' . $pre . ')'
            . $tag_start . $tags . '(?<set_id>' . $set_id . ')(?:' . $spaces . '(?<id>' . $inside_tag . '))?' . $tag_end
            . '(?<closing_tags_after_open>' . $post . ')'
            . '(?<opening_tags_before_content>' . $pre . ')'
            . '(?<content>.*?)'
            . '(?<closing_tags_after_content>' . $post . ')'
            . '(?<opening_tags_before_close>' . $pre . ')'
            . $tag_start . '/\2\3' . $tag_end
            . '(?<closing_tags_after_close>' . $post . ')';
    }

    private static function getRegexes()
    {
        $cache = new RL_Cache;

        if ($cache->exists())
        {
            return $cache->get();
        }

        $regexes = (object) [
            'tag'             => self::getPluginTagRegex(),
            'datatag'         => self::getDataTagRegex(),
            'datatag_current' => self::getDataTagRegex('this'),
            'ifstatement'     => self::getIfStatementRegex(),
            'iftag'           => self::getIfTagRegex(),
        ];

        return $cache->set($regexes);
    }
}
